flatten 20260225
This commit is contained in:
83
tjp/core/math/Accuracy+IO.h
Normal file
83
tjp/core/math/Accuracy+IO.h
Normal file
@@ -0,0 +1,83 @@
|
||||
//
|
||||
// MathIO.h
|
||||
// common
|
||||
//
|
||||
// Created by Timothy Prepscius on 8/4/18.
|
||||
// Copyright © 2018 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Math.h"
|
||||
#include "Accuracy.h"
|
||||
#include <tjp/core/io/bin/IO.h>
|
||||
|
||||
#include "Vector3.hpp"
|
||||
#include "Sphere3.hpp"
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename IO, typename T>
|
||||
void io_r(IO &io, DispatchIO<T> &a)
|
||||
{
|
||||
s64 v;
|
||||
io.any(v);
|
||||
*a.t->v = a.t->m * v;
|
||||
}
|
||||
|
||||
template<typename IO, typename T>
|
||||
void io_w(IO &io, const DispatchIO<T> &a)
|
||||
{
|
||||
s64 v = std::round(*a.t->v / a.t->m);
|
||||
io.any(v);
|
||||
}
|
||||
|
||||
template<typename IO, typename T>
|
||||
void io_(IO &io, Accuracy<T> &a)
|
||||
{
|
||||
auto a_ = makeDispatchIO(a);
|
||||
io.any(a_);
|
||||
}
|
||||
|
||||
template<typename IO, typename R>
|
||||
void io_(IO &io, Accuracy<Vector3<R>> &a)
|
||||
{
|
||||
auto &v = *a.v;
|
||||
|
||||
io.array(
|
||||
with_accuracy(v[0], a.m),
|
||||
with_accuracy(v[1], a.m),
|
||||
with_accuracy(v[2], a.m)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename IO, typename R>
|
||||
void io_(IO &io, Accuracy<Vector2<R>> &a)
|
||||
{
|
||||
auto &v = *a.v;
|
||||
|
||||
io.array(
|
||||
with_accuracy(v[0], a.m),
|
||||
with_accuracy(v[1], a.m)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename IO, typename R>
|
||||
void io_(IO &io, Accuracy<Sphere3<R>> &a)
|
||||
{
|
||||
auto &v = *a.v;
|
||||
|
||||
io.object(
|
||||
"center", with_accuracy(v.center, a.m),
|
||||
"radius", with_accuracy(v.radius, a.m)
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
50
tjp/core/math/Accuracy.h
Normal file
50
tjp/core/math/Accuracy.h
Normal file
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// MathIO.h
|
||||
// common
|
||||
//
|
||||
// Created by Timothy Prepscius on 8/4/18.
|
||||
// Copyright © 2018 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Real.h"
|
||||
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename V>
|
||||
struct Accuracy
|
||||
{
|
||||
V *v;
|
||||
Real m;
|
||||
} ;
|
||||
|
||||
template<typename V>
|
||||
Accuracy<V> with_accuracy(V &v, Real m)
|
||||
{
|
||||
return Accuracy<V> { &v, m };
|
||||
}
|
||||
|
||||
constexpr s64 compile_time_pow10(const int digits)
|
||||
{
|
||||
if (digits == 0)
|
||||
return 1;
|
||||
|
||||
return 10 * compile_time_pow10(digits-1);
|
||||
}
|
||||
|
||||
constexpr Real accuracy_with_digits(const int digits)
|
||||
{
|
||||
if (digits < 0)
|
||||
return 1.0 / compile_time_pow10(-digits);
|
||||
|
||||
return compile_time_pow10(digits);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
71
tjp/core/math/Algorithm+Segment.cpp
Executable file
71
tjp/core/math/Algorithm+Segment.cpp
Executable file
@@ -0,0 +1,71 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#include "Algorithm+Segment.hpp"
|
||||
#include "Math.hpp"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<>
|
||||
std::tuple<math::Segment1<s64>, math::Segment1<s64>> bisectingSegments(const std::vector<math::Segment1<s64>> &v)
|
||||
{
|
||||
typedef s64 Real;
|
||||
|
||||
Real mean = 0;
|
||||
int count = 0;
|
||||
Real l, r;
|
||||
|
||||
bool first = true;
|
||||
for (auto &s: v)
|
||||
{
|
||||
auto [l0, r0] = sortedSegment(s);
|
||||
|
||||
// auto numPoints = 10;
|
||||
// auto d0 = r0 - l0;
|
||||
// for (auto i=0; i<numPoints; ++i)
|
||||
// {
|
||||
// auto v = l0 + i * d0 / numPoints;
|
||||
// middle += v;
|
||||
// count++;
|
||||
// }
|
||||
|
||||
mean += l0 + r0;
|
||||
count += 2;
|
||||
|
||||
if (first)
|
||||
{
|
||||
first = false;
|
||||
l = l0;
|
||||
r = r0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (l0 < l)
|
||||
l = l0;
|
||||
if (r0 > r)
|
||||
r = r0;
|
||||
}
|
||||
}
|
||||
|
||||
if (count > 0)
|
||||
mean = mean / count;
|
||||
|
||||
// auto middle = (l + r) / 2;
|
||||
// auto middle = l + (r - l) / 2;
|
||||
|
||||
auto ls = math::Segment1<Real> { l, mean };
|
||||
auto rs = math::Segment1<Real> { mean, r };
|
||||
return { ls, rs };
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
22
tjp/core/math/Algorithm+Segment.hpp
Executable file
22
tjp/core/math/Algorithm+Segment.hpp
Executable file
@@ -0,0 +1,22 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Algorithm.h"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
#include "Algorithm+Segment.inl"
|
||||
225
tjp/core/math/Algorithm+Segment.inl
Executable file
225
tjp/core/math/Algorithm+Segment.inl
Executable file
@@ -0,0 +1,225 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Algorithm.h"
|
||||
#include "Math.hpp"
|
||||
#include "Zero.h"
|
||||
#include "Segment1.hpp"
|
||||
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
|
||||
template<typename Real>
|
||||
std::tuple<Real,Real> sortedSegment(const Segment1<Real> &segment)
|
||||
{
|
||||
if (segment.begin < segment.end)
|
||||
{
|
||||
return { segment.begin, segment.end };
|
||||
}
|
||||
|
||||
return { segment.end, segment.begin };
|
||||
}
|
||||
|
||||
template<typename S, typename R>
|
||||
bool intersects_segment (const S &l, const S &r, R error)
|
||||
{
|
||||
/*
|
||||
abs((l.l+l.r)/2 - (r.l+r.r))/2 <= abs(l.r-l.l)/2 + abs(r.r-r.l)/2 + error
|
||||
|
||||
abs( (l.l+l.r) - (r.l+r.r) )/2 <= (abs(l.r-l.l) + abs(r.r-r.l)) / 2
|
||||
abs( (l.l+l.r) + (r.l+r.r) ) <= 2 * abs(l.r-l.l) + abs(r.r-r.l) + 2*error
|
||||
|
||||
*/
|
||||
|
||||
// return distance((l.begin+l.end),(r.begin+r.end)) <= length(l) + length(r) + 2*error;
|
||||
|
||||
auto [l0,r0] = sortedSegment(l);
|
||||
auto [l1,r1] = sortedSegment(r);
|
||||
|
||||
if (l1 <= l0+error && r1 >= r0-error)
|
||||
return true;
|
||||
|
||||
if (l1 >= l0-error && l1 <= r0+error)
|
||||
return true;
|
||||
|
||||
if (r1 >= l0-error && r1 <= r0+error)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
template<typename S>
|
||||
bool intersects_segment (const S &l, const S &r)
|
||||
{
|
||||
/*
|
||||
abs((l.l+l.r)/2 - (r.l+r.r))/2 <= abs(l.r-l.l)/2 + abs(r.r-r.l)/2 + error
|
||||
|
||||
abs( (l.l+l.r) - (r.l+r.r) )/2 <= (abs(l.r-l.l) + abs(r.r-r.l)) / 2
|
||||
abs( (l.l+l.r) + (r.l+r.r) ) <= 2 * abs(l.r-l.l) + abs(r.r-r.l) + 2*error
|
||||
|
||||
*/
|
||||
|
||||
// return distance((l.begin+l.end),(r.begin+r.end)) <= length(l) + length(r) + 2*error;
|
||||
|
||||
auto [l0,r0] = sortedSegment(l);
|
||||
auto [l1,r1] = sortedSegment(r);
|
||||
|
||||
if (l1 <= l0 && r1 >= r0)
|
||||
return true;
|
||||
|
||||
if (l1 >= l0 && l1 <= r0)
|
||||
return true;
|
||||
|
||||
if (r1 >= l0 && r1 <= r0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
bool intersects(const Segment1<Real> &s0, const Segment1<Real> &s1, const Real &error)
|
||||
{
|
||||
return intersects_segment(s0, s1, error);
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
bool intersects(const Segment1<Real> &s0, const Segment1<Real> &s1)
|
||||
{
|
||||
return intersects_segment(s0, s1);
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Real distance(const Segment1<Real> &segment, const Real &p)
|
||||
{
|
||||
auto [l, r] = sortedSegment(segment);
|
||||
|
||||
if (p <= l)
|
||||
return l - p;
|
||||
if (p >= r)
|
||||
return p - r;
|
||||
|
||||
return -std::min(distance(p,l), distance(p,r));
|
||||
}
|
||||
|
||||
template<typename S, typename R>
|
||||
bool intersects_segment_point (const S &s, const R &p, R error)
|
||||
{
|
||||
auto [l, r] = sortedSegment(s);
|
||||
return (l <= p) && (p <= r);
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
bool contains_segment (const S &l, const S &r)
|
||||
{
|
||||
auto [l0,r0] = sortedSegment(l);
|
||||
auto [l1,r1] = sortedSegment(r);
|
||||
|
||||
if (l0 <= l1 && r0 >= r1)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename S, typename R>
|
||||
bool contains_segment (const S &l, const S &r, R error)
|
||||
{
|
||||
auto [l0,r0] = sortedSegment(l);
|
||||
auto [l1,r1] = sortedSegment(r);
|
||||
|
||||
if (l0 <= l1+error && r0 >= r1-error)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template<typename Real>
|
||||
bool contains (const math::Segment1<Real> &l, const math::Segment1<Real> &r)
|
||||
{
|
||||
return contains_segment(l, r);
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
bool contains (const math::Segment1<Real> &l, const math::Segment1<Real> &r, Real error)
|
||||
{
|
||||
return contains_segment(l, r, error);
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
std::tuple<math::Segment1<Real>, math::Segment1<Real>> bisectingSegments(const std::vector<math::Segment1<Real>> &v)
|
||||
{
|
||||
Real l, r;
|
||||
bool first = true;
|
||||
for (auto &s: v)
|
||||
{
|
||||
auto [l0, r0] = sortedSegment(s);
|
||||
if (first)
|
||||
{
|
||||
first = false;
|
||||
l = l0;
|
||||
r = r0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (l0 < l)
|
||||
l = l0;
|
||||
if (r0 > r)
|
||||
r = r0;
|
||||
}
|
||||
}
|
||||
|
||||
auto middle = (l + r) / 2;
|
||||
// auto middle = l + (r - l) / 2;
|
||||
|
||||
auto ls = math::Segment1<Real> { l, middle };
|
||||
auto rs = math::Segment1<Real> { middle, r };
|
||||
return { ls, rs };
|
||||
}
|
||||
|
||||
template<>
|
||||
std::tuple<math::Segment1<s64>, math::Segment1<s64>> bisectingSegments(const std::vector<math::Segment1<s64>> &v);
|
||||
|
||||
|
||||
template<typename Real>
|
||||
math::Segment1<Real> segmentContaining(const std::vector<math::Segment1<Real>> &v, const math::Segment1<Real> &zero)
|
||||
{
|
||||
if (v.empty())
|
||||
return zero;
|
||||
|
||||
Real l, r;
|
||||
bool first = true;
|
||||
for (auto &s: v)
|
||||
{
|
||||
auto [l0, r0] = sortedSegment(s);
|
||||
if (first)
|
||||
{
|
||||
first = false;
|
||||
l = l0;
|
||||
r = r0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (l0 < l)
|
||||
l = l0;
|
||||
if (r0 > r)
|
||||
r = r0;
|
||||
}
|
||||
}
|
||||
|
||||
auto s = math::Segment1<Real> { l, r };
|
||||
return s;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
102
tjp/core/math/Algorithm+SimplifyCurve.cpp
Executable file
102
tjp/core/math/Algorithm+SimplifyCurve.cpp
Executable file
@@ -0,0 +1,102 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#include "Algorithm+SimplifyCurve.hpp"
|
||||
|
||||
#include "Math.hpp"
|
||||
#include "Algorithm.hpp"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
typedef math::Vector3r SimplifyVertex;
|
||||
typedef core::MemoryArray<SimplifyVertex> SimplifyPoints;
|
||||
|
||||
// read this and made this, not sure if the same
|
||||
// https://towardsdatascience.com/simplify-polylines-with-the-douglas-peucker-algorithm-ac8ed487a4a1
|
||||
|
||||
typedef std::vector<size_t> SimplifyResult;
|
||||
|
||||
void simplify(SimplifyResult &result, const SimplifyPoints &points, size_t from, size_t to, size_t iterations)
|
||||
{
|
||||
if (to == from)
|
||||
return;
|
||||
|
||||
Segment3<Real> segment { points[from], points[to] };
|
||||
|
||||
size_t farthest = 0;
|
||||
Real farthestDistance = 0;
|
||||
|
||||
for (auto i = from+1; i!=to; ++i)
|
||||
{
|
||||
auto distance = math::distance(segment, points[i]);
|
||||
if (!farthest || distance > farthestDistance)
|
||||
{
|
||||
farthest = i;
|
||||
farthestDistance = distance;
|
||||
}
|
||||
}
|
||||
|
||||
if (farthest && iterations > 0)
|
||||
{
|
||||
simplify(result, points, from , farthest, iterations-1);
|
||||
simplify(result, points, farthest, to, iterations-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (farthest)
|
||||
result.push_back(farthest);
|
||||
|
||||
result.push_back(to);
|
||||
}
|
||||
}
|
||||
|
||||
SimplifyResult simplify(const SimplifyPoints &points, size_t iterations)
|
||||
{
|
||||
if (points.size() < 2)
|
||||
return SimplifyResult {};
|
||||
|
||||
size_t farthest = 0;
|
||||
auto begin = 0;
|
||||
auto end = points.size()-1;
|
||||
Real farthestDistance = 0;
|
||||
|
||||
SimplifyResult result;
|
||||
result.push_back(begin);
|
||||
|
||||
if (points.front() == points.back())
|
||||
{
|
||||
for (auto to=1; to!=end; ++to)
|
||||
{
|
||||
auto distance = math::distance(points[begin], points[to]);
|
||||
if (!farthest || distance > farthestDistance)
|
||||
{
|
||||
farthest = to;
|
||||
farthestDistance = distance;
|
||||
}
|
||||
}
|
||||
|
||||
simplify(result, points, begin, farthest, iterations-1);
|
||||
|
||||
if (farthest != end)
|
||||
simplify(result, points, farthest, end, iterations-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
simplify(result, points, begin, end, iterations);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
49
tjp/core/math/Algorithm+SimplifyCurve.hpp
Executable file
49
tjp/core/math/Algorithm+SimplifyCurve.hpp
Executable file
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Algorithm.h"
|
||||
#include <tjp/core/containers/MemoryArray.hpp>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
std::vector<size_t> simplify(const core::MemoryArray<math::Vector3r> &points, size_t iterations);
|
||||
|
||||
template<typename T, typename F>
|
||||
std::vector<size_t> simplify(const T &points_, size_t iterations, F &&f)
|
||||
{
|
||||
std::vector<math::Vector3r> points;
|
||||
for (auto &v: points_)
|
||||
{
|
||||
points.push_back(f(v));
|
||||
}
|
||||
|
||||
return simplify(points, iterations);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T simplified(const T &t, const std::vector<size_t> &indices)
|
||||
{
|
||||
T result;
|
||||
result.reserve(indices.size());
|
||||
for (auto &i : indices)
|
||||
{
|
||||
result.push_back(t[i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
197
tjp/core/math/Algorithm+Split+BigInt.inl
Executable file
197
tjp/core/math/Algorithm+Split+BigInt.inl
Executable file
@@ -0,0 +1,197 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Algorithm+Split.hpp"
|
||||
#include "Algorithm.inl"
|
||||
#include "Math.hpp"
|
||||
#include "BigInt.h"
|
||||
#include "BigDecimal.h"
|
||||
|
||||
#include <tjp/core/log/Log.h>
|
||||
#include <tjp/core/log/LogOf.h>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename C, typename D, typename I>
|
||||
Sphere1<C, D> sphereContaining_points(I i, I end, const Sphere1<C, D> &emptyValue)
|
||||
{
|
||||
if (i == end)
|
||||
return emptyValue;
|
||||
|
||||
auto &s = *i;
|
||||
auto l = s;
|
||||
auto r = s;
|
||||
|
||||
sLogDebug("sphereContaining_spheres", logVar(s));
|
||||
|
||||
for (++i; i != end; ++i)
|
||||
{
|
||||
auto &v = *i;
|
||||
|
||||
l = min_value(l, v);
|
||||
r = max_value(r, v);
|
||||
|
||||
sLogDebug("sphereContaining_spheres", logVar(*i) << logVar(l) << logVar(r));
|
||||
}
|
||||
|
||||
auto c = (l+r)/2;
|
||||
auto rmc = distance(r,c);
|
||||
auto cml = distance(c,l);
|
||||
|
||||
sLogDebug("sphereContaining_spheres", logVar(c) << logVar(rmc) << logVar(cml));
|
||||
|
||||
auto radius = max_value(rmc, cml);
|
||||
|
||||
sLogDebug("sphereContaining_spheres", logVar(c) << logVar(radius));
|
||||
|
||||
return { c, radius };
|
||||
}
|
||||
|
||||
template<typename C, typename D>
|
||||
std::tuple<math::Sphere1<C,D>, math::Sphere1<C,D>> bisectingRegions(const std::vector<C> &translates_)
|
||||
{
|
||||
debug_assert(!translates_.empty());
|
||||
debug_assert(translates_.size() > 1);
|
||||
|
||||
auto sortable = translates_;
|
||||
std::sort(sortable.begin(), sortable.end());
|
||||
|
||||
auto begin = sortable.begin();
|
||||
auto halfL = begin + sortable.size()/2;
|
||||
auto halfR = halfL + 1;
|
||||
auto end = sortable.end();
|
||||
|
||||
auto l = sphereContaining_points(begin, halfR, Sphere1<C,D>::Zero);
|
||||
auto r = sphereContaining_points(halfR, end, Sphere1<C,D>::Zero);
|
||||
|
||||
#ifdef _DEBUG
|
||||
for (auto i=begin; i != halfR; ++i)
|
||||
{
|
||||
if (!intersects(l, *i))// || intersects(r, *i))
|
||||
{
|
||||
for (auto i=begin; i!=halfR; ++i)
|
||||
{
|
||||
sLogDebug("debug", "L " << logVar(*i));
|
||||
}
|
||||
|
||||
for (auto i=halfR; i!=end; ++i)
|
||||
{
|
||||
sLogDebug("debug", "R " << logVar(*i));
|
||||
}
|
||||
|
||||
sLogDebug("debug", logVar(l) << logVar(r) << logVar(*i) << logVar(distance(l.center, *i)));
|
||||
|
||||
{
|
||||
auto sortable = translates_;
|
||||
std::sort(sortable.begin(), sortable.end());
|
||||
|
||||
auto begin = sortable.begin();
|
||||
auto halfL = begin + sortable.size()/2;
|
||||
auto halfR = halfL + 1;
|
||||
auto l = sphereContaining_points(begin, halfR, Sphere1<C,D>::Zero);
|
||||
intersects(l, *i);
|
||||
}
|
||||
}
|
||||
debug_assert(intersects(l, *i));
|
||||
// debug_assert(!intersects(r, *i));
|
||||
}
|
||||
|
||||
for (auto i=halfR; i != end; ++i)
|
||||
{
|
||||
if (!intersects(r, *i))
|
||||
{
|
||||
for (auto i=begin; i!=halfR; ++i)
|
||||
{
|
||||
sLogDebug("debug", "L " << logVar(*i));
|
||||
}
|
||||
|
||||
for (auto i=halfR; i!=end; ++i)
|
||||
{
|
||||
sLogDebug("debug", "R " << logVar(*i));
|
||||
}
|
||||
|
||||
sLogDebug("debug", logVar(l) << logVar(r) << logVar(*i) << logVar(distance(r.center, *i)));
|
||||
auto r = sphereContaining_points(halfR, end, Sphere1<C,D>::Zero);
|
||||
intersects(r, *i);
|
||||
}
|
||||
|
||||
debug_assert(intersects(r, *i));
|
||||
// debug_assert(!intersects(l, *i));
|
||||
}
|
||||
#endif
|
||||
|
||||
return { l, r };
|
||||
}
|
||||
|
||||
template<typename C, typename D, typename I>
|
||||
Sphere1<C, D> sphereContaining_spheres(I begin, I end, const Sphere1<C, D> &emptyValue)
|
||||
{
|
||||
if (begin == end)
|
||||
return emptyValue;
|
||||
|
||||
auto c = begin->center;
|
||||
|
||||
auto i=begin;
|
||||
++i;
|
||||
|
||||
size_t count = 0;
|
||||
for (;i!=end; ++i)
|
||||
{
|
||||
c = c + i->center;
|
||||
count++;
|
||||
}
|
||||
|
||||
c = c / count;
|
||||
auto radius = distance(begin->center, c) + begin->radius;
|
||||
|
||||
i = begin;
|
||||
++i;
|
||||
|
||||
for (;i!=end; ++i)
|
||||
{
|
||||
auto v = distance(i->center, c) + i->radius;
|
||||
radius = max_value(radius, v);
|
||||
}
|
||||
|
||||
return { c, radius };
|
||||
}
|
||||
|
||||
template<typename C, typename D>
|
||||
math::Sphere1<C, D> sphereContaining(const std::vector<math::Sphere1<C, D>> &spheres, const math::Sphere1<C, D> &emptyValue)
|
||||
{
|
||||
return sphereContaining_spheres<C, D>(spheres.begin(), spheres.end(), emptyValue);
|
||||
}
|
||||
|
||||
template<typename Real, typename T, typename F>
|
||||
math::Sphere3<Real> sphereContaining(const math::Sphere3<Real> &emptyValue, T &t, F &&f)
|
||||
{
|
||||
std::vector<math::Sphere3<Real>> spheres;
|
||||
for (auto &v : t)
|
||||
spheres.push_back(f(v));
|
||||
|
||||
return sphereContaining(spheres, emptyValue);
|
||||
}
|
||||
|
||||
template<typename C, typename D, typename T, typename F>
|
||||
math::Sphere1<C, D> sphereContaining(const math::Sphere1<C, D> &emptyValue, T &t, F &&f)
|
||||
{
|
||||
std::vector<math::Sphere1<C, D>> spheres;
|
||||
for (auto &v : t)
|
||||
spheres.push_back(f(v));
|
||||
|
||||
return sphereContaining(spheres, emptyValue);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
178
tjp/core/math/Algorithm+Split.cpp
Executable file
178
tjp/core/math/Algorithm+Split.cpp
Executable file
@@ -0,0 +1,178 @@
|
||||
//
|
||||
// Math.cpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#include "Algorithm+Split.hpp"
|
||||
#include "Sphere3.hpp"
|
||||
|
||||
|
||||
#include <tjp/core/assert/debug_assert.h>
|
||||
|
||||
#define dynamic_cast static_cast
|
||||
#define GTE_NO_LOGGER
|
||||
#include <Mathematics/ApprOrthogonalLine3.h>
|
||||
#include <Mathematics/ContSphere3.h>
|
||||
#include <Mathematics/MinimumVolumeSphere3.h>
|
||||
#include <Mathematics/IntrSphere3Frustum3.h>
|
||||
#include <Mathematics/IntrRay3Sphere3.h>
|
||||
#include <Mathematics/IntrSphere3Cone3.h>
|
||||
#include <Mathematics/DistPointRay.h>
|
||||
#include <Mathematics/IntrRay3Plane3.h>
|
||||
#include <Mathematics/DistPointRay.h>
|
||||
#include <Mathematics/DistPointSegment.h>
|
||||
|
||||
#include "GTE_convert.hpp"
|
||||
#undef dynamic_cast
|
||||
|
||||
#include <vector>
|
||||
#include <tjp/core/log/Log.h>
|
||||
#include <tjp/core/log/LogOf.h>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
std::tuple<math::Sphere3<Real>, math::Sphere3<Real>> bisectingRegions_(const std::vector<math::Vector3<Real>> &translates_)
|
||||
{
|
||||
std::vector<gte::Vector3<Real>> translates;
|
||||
|
||||
for (auto &p : translates_)
|
||||
translates.push_back(gte_c(p));
|
||||
|
||||
gte::ApprOrthogonalLine3<Real> orthogonalLineFit;
|
||||
orthogonalLineFit.Fit((int)translates.size(), translates.data());
|
||||
auto &line = orthogonalLineFit.GetParameters();
|
||||
|
||||
std::vector<gte::Vector3<Real>> left, right;
|
||||
for (auto &t : translates)
|
||||
{
|
||||
if (gte::Dot((t - line.origin), line.direction) > 0)
|
||||
right.push_back(t);
|
||||
else
|
||||
left.push_back(t);
|
||||
}
|
||||
|
||||
// {
|
||||
// auto mean = statistics::mean<Vector3r::Super>(left);
|
||||
// auto stdev = statistics::stdev<Real, Vector3r::Super>(left, mean);
|
||||
//
|
||||
// for (auto &t : left)
|
||||
// {
|
||||
// if (length(t - mean) < 2*stdev)
|
||||
// culledLeft.push_back(t);
|
||||
// }
|
||||
// }
|
||||
// {
|
||||
// auto mean = statistics::mean<Vector3r::Super>(right);
|
||||
// auto stdev = statistics::stdev<Real, Vector3r::Super>(right, mean);
|
||||
//
|
||||
// vector<Vector3r::Super> culled;
|
||||
// for (auto &t : right)
|
||||
// {
|
||||
// if (length(t - mean) < 2*stdev)
|
||||
// culledRight.push_back(t);
|
||||
// }
|
||||
// }
|
||||
|
||||
sLogRelease("wired::split", logVar(left.size()) << logVar(right.size()));
|
||||
|
||||
// ensure there is data in both sets
|
||||
if (left.empty())
|
||||
left = right;
|
||||
|
||||
if (right.empty())
|
||||
right = left;
|
||||
|
||||
gte::Sphere3<Real> leftSphere;
|
||||
// gte::MinimumVolumeSphere3<Real, Real> leftSphereMinimum;
|
||||
gte::GetContainer(left, leftSphere);
|
||||
|
||||
gte::Sphere3<Real> rightSphere;
|
||||
// gte::MinimumVolumeSphere3<Real, Real> rightSphereMinimum;
|
||||
gte::GetContainer(right, rightSphere);
|
||||
|
||||
return { gte_c(leftSphere), gte_c(rightSphere) };
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
std::tuple<math::Sphere3<r32>, math::Sphere3<r32>> bisectingRegions(const std::vector<math::Vector3<r32>> &points)
|
||||
{
|
||||
return bisectingRegions_(points);
|
||||
}
|
||||
|
||||
template<>
|
||||
std::tuple<math::Sphere3<r64>, math::Sphere3<r64>> bisectingRegions(const std::vector<math::Vector3<r64>> &points)
|
||||
{
|
||||
return bisectingRegions_(points);
|
||||
}
|
||||
|
||||
// ---------------------------------
|
||||
|
||||
template<typename Real>
|
||||
Sphere3<Real> sphereContaining_(const std::vector<Vector3<Real>> &points, const Sphere3<Real> &emptyValue)
|
||||
{
|
||||
if (points.empty())
|
||||
return emptyValue;
|
||||
|
||||
std::vector<gte::Vector3<Real>> points_;
|
||||
points_.reserve(points.size());
|
||||
for (auto &p: points)
|
||||
points_.push_back(gte_c(p));
|
||||
|
||||
gte::Sphere3<Real> sphere;
|
||||
gte::GetContainer(points_, sphere);
|
||||
|
||||
return gte_c(sphere);
|
||||
}
|
||||
|
||||
template<>
|
||||
Sphere3<r64> sphereContaining(const std::vector<Vector3<r64>> &points, const Sphere3<r64> &emptyValue)
|
||||
{
|
||||
return sphereContaining_(points, emptyValue);
|
||||
}
|
||||
|
||||
|
||||
template<typename Real>
|
||||
Sphere3<Real> sphereContaining_(const std::vector<Sphere3<Real>> &spheres, const Sphere3<Real> &emptyValue)
|
||||
{
|
||||
if (spheres.empty())
|
||||
return emptyValue;
|
||||
|
||||
auto sphere = gte_c(spheres.front());
|
||||
if (sphere.radius == Sphere3<Real>::Infinite.radius)
|
||||
return Sphere3<Real>::Infinite;
|
||||
|
||||
for (auto i=spheres.begin()+1; i!=spheres.end(); ++i)
|
||||
{
|
||||
if (i->radius == Sphere3<Real>::Infinite.radius)
|
||||
return Sphere3<Real>::Infinite;
|
||||
|
||||
gte::Sphere3<Real> merge;
|
||||
gte::MergeContainers(sphere, gte_c(*i), merge);
|
||||
sphere = merge;
|
||||
}
|
||||
|
||||
return gte_c(sphere);
|
||||
}
|
||||
|
||||
template<>
|
||||
Sphere3<r32> sphereContaining(const std::vector<Sphere3<r32>> &spheres, const Sphere3<r32> &emptyValue)
|
||||
{
|
||||
return sphereContaining_(spheres, emptyValue);
|
||||
}
|
||||
|
||||
template<>
|
||||
Sphere3<r64> sphereContaining(const std::vector<Sphere3<r64>> &spheres, const Sphere3<r64> &emptyValue)
|
||||
{
|
||||
return sphereContaining_(spheres, emptyValue);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
34
tjp/core/math/Algorithm+Split.hpp
Executable file
34
tjp/core/math/Algorithm+Split.hpp
Executable file
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Algorithm.hpp"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<>
|
||||
std::tuple<math::Sphere3<r32>, math::Sphere3<r32>> bisectingRegions(const std::vector<math::Vector3<r32>> &points);
|
||||
|
||||
template<>
|
||||
std::tuple<math::Sphere3<r64>, math::Sphere3<r64>> bisectingRegions(const std::vector<math::Vector3<r64>> &points);
|
||||
|
||||
|
||||
template<>
|
||||
math::Sphere3<r32> sphereContaining(const std::vector<math::Sphere3<r32>> &spheres, const math::Sphere3<r32> &emptyValue);
|
||||
|
||||
template<>
|
||||
math::Sphere3<r64> sphereContaining(const std::vector<math::Sphere3<r64>> &spheres, const math::Sphere3<r64> &emptyValue);
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
#include "Algorithm+Split.inl"
|
||||
195
tjp/core/math/Algorithm+Split.inl
Executable file
195
tjp/core/math/Algorithm+Split.inl
Executable file
@@ -0,0 +1,195 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Algorithm+Split.hpp"
|
||||
#include "Algorithm.inl"
|
||||
#include "Math.hpp"
|
||||
|
||||
#include <tjp/core/log/Log.h>
|
||||
#include <tjp/core/log/LogOf.h>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename C, typename D, typename I>
|
||||
Sphere1<C, D> sphereContaining_points(I i, I end, const Sphere1<C, D> &emptyValue)
|
||||
{
|
||||
if (i == end)
|
||||
return emptyValue;
|
||||
|
||||
auto &s = *i;
|
||||
auto l = s;
|
||||
auto r = s;
|
||||
|
||||
sLogDebug("sphereContaining_spheres", logVar(s));
|
||||
|
||||
for (++i; i != end; ++i)
|
||||
{
|
||||
auto &v = *i;
|
||||
|
||||
l = min_value(l, v);
|
||||
r = max_value(r, v);
|
||||
|
||||
sLogDebug("sphereContaining_spheres", logVar(*i) << logVar(l) << logVar(r));
|
||||
}
|
||||
|
||||
auto c = (l+r)/2;
|
||||
auto rmc = distance(r,c);
|
||||
auto cml = distance(c,l);
|
||||
|
||||
sLogDebug("sphereContaining_spheres", logVar(c) << logVar(rmc) << logVar(cml));
|
||||
|
||||
auto radius = max_value(rmc, cml);
|
||||
|
||||
sLogDebug("sphereContaining_spheres", logVar(c) << logVar(radius));
|
||||
|
||||
return { c, radius };
|
||||
}
|
||||
|
||||
template<typename C, typename D>
|
||||
std::tuple<math::Sphere1<C,D>, math::Sphere1<C,D>> bisectingRegions(const std::vector<C> &translates_)
|
||||
{
|
||||
debug_assert(!translates_.empty());
|
||||
debug_assert(translates_.size() > 1);
|
||||
|
||||
auto sortable = translates_;
|
||||
std::sort(sortable.begin(), sortable.end());
|
||||
|
||||
auto begin = sortable.begin();
|
||||
auto halfL = begin + sortable.size()/2;
|
||||
auto halfR = halfL + 1;
|
||||
auto end = sortable.end();
|
||||
|
||||
auto l = sphereContaining_points(begin, halfR, Sphere1<C,D>::Zero);
|
||||
auto r = sphereContaining_points(halfR, end, Sphere1<C,D>::Zero);
|
||||
|
||||
#ifdef _DEBUG
|
||||
for (auto i=begin; i != halfR; ++i)
|
||||
{
|
||||
if (!intersects(l, *i))// || intersects(r, *i))
|
||||
{
|
||||
for (auto i=begin; i!=halfR; ++i)
|
||||
{
|
||||
sLogDebug("debug", "L " << logVar(*i));
|
||||
}
|
||||
|
||||
for (auto i=halfR; i!=end; ++i)
|
||||
{
|
||||
sLogDebug("debug", "R " << logVar(*i));
|
||||
}
|
||||
|
||||
sLogDebug("debug", logVar(l) << logVar(r) << logVar(*i) << logVar(distance(l.center, *i)));
|
||||
|
||||
{
|
||||
auto sortable = translates_;
|
||||
std::sort(sortable.begin(), sortable.end());
|
||||
|
||||
auto begin = sortable.begin();
|
||||
auto halfL = begin + sortable.size()/2;
|
||||
auto halfR = halfL + 1;
|
||||
auto l = sphereContaining_points(begin, halfR, Sphere1<C,D>::Zero);
|
||||
intersects(l, *i);
|
||||
}
|
||||
}
|
||||
debug_assert(intersects(l, *i));
|
||||
// debug_assert(!intersects(r, *i));
|
||||
}
|
||||
|
||||
for (auto i=halfR; i != end; ++i)
|
||||
{
|
||||
if (!intersects(r, *i))
|
||||
{
|
||||
for (auto i=begin; i!=halfR; ++i)
|
||||
{
|
||||
sLogDebug("debug", "L " << logVar(*i));
|
||||
}
|
||||
|
||||
for (auto i=halfR; i!=end; ++i)
|
||||
{
|
||||
sLogDebug("debug", "R " << logVar(*i));
|
||||
}
|
||||
|
||||
sLogDebug("debug", logVar(l) << logVar(r) << logVar(*i) << logVar(distance(r.center, *i)));
|
||||
auto r = sphereContaining_points(halfR, end, Sphere1<C,D>::Zero);
|
||||
intersects(r, *i);
|
||||
}
|
||||
|
||||
debug_assert(intersects(r, *i));
|
||||
// debug_assert(!intersects(l, *i));
|
||||
}
|
||||
#endif
|
||||
|
||||
return { l, r };
|
||||
}
|
||||
|
||||
template<typename C, typename D, typename I>
|
||||
Sphere1<C, D> sphereContaining_spheres(I begin, I end, const Sphere1<C, D> &emptyValue)
|
||||
{
|
||||
if (begin == end)
|
||||
return emptyValue;
|
||||
|
||||
auto c = begin->center;
|
||||
|
||||
auto i=begin;
|
||||
++i;
|
||||
|
||||
size_t count = 0;
|
||||
for (;i!=end; ++i)
|
||||
{
|
||||
c = c + i->center;
|
||||
count++;
|
||||
}
|
||||
|
||||
c = c / count;
|
||||
auto radius = distance(begin->center, c) + begin->radius;
|
||||
|
||||
i = begin;
|
||||
++i;
|
||||
|
||||
for (;i!=end; ++i)
|
||||
{
|
||||
auto v = distance(i->center, c) + i->radius;
|
||||
radius = max_value(radius, v);
|
||||
}
|
||||
|
||||
return { c, radius };
|
||||
}
|
||||
|
||||
template<typename C, typename D>
|
||||
math::Sphere1<C, D> sphereContaining(const std::vector<math::Sphere1<C, D>> &spheres, const math::Sphere1<C, D> &emptyValue)
|
||||
{
|
||||
return sphereContaining_spheres<C, D>(spheres.begin(), spheres.end(), emptyValue);
|
||||
}
|
||||
|
||||
template<typename Real, typename T, typename F>
|
||||
math::Sphere3<Real> sphereContaining(const math::Sphere3<Real> &emptyValue, T &t, F &&f)
|
||||
{
|
||||
std::vector<math::Sphere3<Real>> spheres;
|
||||
for (auto &v : t)
|
||||
spheres.push_back(f(v));
|
||||
|
||||
return sphereContaining(spheres, emptyValue);
|
||||
}
|
||||
|
||||
template<typename C, typename D, typename T, typename F>
|
||||
math::Sphere1<C, D> sphereContaining(const math::Sphere1<C, D> &emptyValue, T &t, F &&f)
|
||||
{
|
||||
std::vector<math::Sphere1<C, D>> spheres;
|
||||
for (auto &v : t)
|
||||
spheres.push_back(f(v));
|
||||
|
||||
return sphereContaining(spheres, emptyValue);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
414
tjp/core/math/Algorithm.cpp
Executable file
414
tjp/core/math/Algorithm.cpp
Executable file
@@ -0,0 +1,414 @@
|
||||
//
|
||||
// Math.cpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#include "Algorithm.h"
|
||||
#include "Sphere3.hpp"
|
||||
|
||||
#include <tjp/core/assert/debug_assert.h>
|
||||
#include <tjp/core/algorithm/is_in.hpp>
|
||||
|
||||
#define GTE_NO_LOGGER
|
||||
#include <Mathematics/ApprOrthogonalLine3.h>
|
||||
#include <Mathematics/ContSphere3.h>
|
||||
#include <Mathematics/MinimumVolumeSphere3.h>
|
||||
#include <Mathematics/IntrSphere3Frustum3.h>
|
||||
#include <Mathematics/IntrRay3Sphere3.h>
|
||||
#include <Mathematics/IntrSphere3Cone3.h>
|
||||
#include <Mathematics/IntrSphere3Sphere3.h>
|
||||
#include <Mathematics/IntrOrientedBox3Frustum3.h>
|
||||
#include <Mathematics/DistPointRay.h>
|
||||
#include <Mathematics/DistPointSegment.h>
|
||||
#include <Mathematics/DistPoint3Plane3.h>
|
||||
#include <Mathematics/DistLine3Triangle3.h>
|
||||
#include <Mathematics/IntrRay3Plane3.h>
|
||||
|
||||
#include "GTE_convert.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
// ---------------------------------
|
||||
|
||||
template<typename R>
|
||||
R distance_ (const math::Ray3<R> &ray, const math::Vector3<R> &r)
|
||||
{
|
||||
auto ray_ = gte_c(ray);
|
||||
auto point_ = gte_c(r);
|
||||
|
||||
gte::DCPPoint3Ray3<R> query;
|
||||
auto result = query(point_, ray_);
|
||||
|
||||
return result.distance;
|
||||
}
|
||||
|
||||
template<>
|
||||
r32 distance (const math::Ray3<r32> &ray, const math::Vector3<r32> &r)
|
||||
{
|
||||
return distance_(ray, r);
|
||||
}
|
||||
|
||||
template<>
|
||||
r64 distance (const math::Ray3<r64> &ray, const math::Vector3<r64> &r)
|
||||
{
|
||||
return distance_(ray, r);
|
||||
}
|
||||
|
||||
// ---------------------------------
|
||||
|
||||
template<typename R>
|
||||
R distance_ (const math::Segment3<R> &ray, const math::Vector3<R> &r)
|
||||
{
|
||||
auto segment_ = gte_c(ray);
|
||||
auto point_ = gte_c(r);
|
||||
|
||||
gte::DCPPoint3Segment3<R> query;
|
||||
auto result = query(point_, segment_);
|
||||
|
||||
return result.distance;
|
||||
}
|
||||
|
||||
template<>
|
||||
r32 distance (const math::Segment3<r32> &ray, const math::Vector3<r32> &r)
|
||||
{
|
||||
return distance_(ray, r);
|
||||
}
|
||||
|
||||
template<>
|
||||
r64 distance (const math::Segment3<r64> &ray, const math::Vector3<r64> &r)
|
||||
{
|
||||
return distance_(ray, r);
|
||||
}
|
||||
// ---------------------------------
|
||||
|
||||
template<typename Real>
|
||||
bool intersects_ (const Sphere3<Real> &sphere, const Frustum3<Real> &frustum)
|
||||
{
|
||||
auto sphere_ = gte_c(sphere);
|
||||
auto frustum_ = gte_c(frustum);
|
||||
|
||||
gte::TIQuery<Real, gte::Sphere3<Real>, gte::Frustum3<Real>> query;
|
||||
auto result = query(sphere_, frustum_);
|
||||
|
||||
return result.intersect;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
bool intersects_ (const Sphere3<Real> &sphere, const Cone3<Real> &cone)
|
||||
{
|
||||
auto sphere_ = gte_c(sphere);
|
||||
auto cone_ = gte_c(cone);
|
||||
|
||||
gte::TIQuery<Real, gte::Sphere3<Real>, gte::Cone3<Real>> query;
|
||||
auto result = query(sphere_, cone_);
|
||||
|
||||
return result.intersect;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
bool intersects_ (const Box3<Real> &lhs_, const Frustum3<Real> &rhs_)
|
||||
{
|
||||
auto lhs = gte_c(lhs_);
|
||||
auto rhs = gte_c(rhs_);
|
||||
|
||||
gte::TIQuery<Real, decltype(lhs), decltype(rhs)> query;
|
||||
auto result = query(lhs, rhs);
|
||||
|
||||
return result.intersect;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
bool intersects_ (const Vector3<Real> &point, const Frustum3<Real> &frustum)
|
||||
{
|
||||
auto frustum_ = gte_c(frustum);
|
||||
auto point_ = gte_c(point);
|
||||
|
||||
gte::DCPQuery<Real, gte::Vector3<Real>, gte::Frustum3<Real>> query;
|
||||
auto result = query(point_, frustum_);
|
||||
return result.distance == 0;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
std::tuple<bool, Vector3<Real>> intersection_ (const Ray3<Real> &ray, const Sphere3<Real> &sphere)
|
||||
{
|
||||
auto ray_ = gte_c(ray);
|
||||
auto sphere_ = gte_c(sphere);
|
||||
|
||||
gte::FIQuery<Real, gte::Ray3<Real>, gte::Sphere3<Real>> query;
|
||||
auto result = query(ray_, sphere_);
|
||||
|
||||
if (result.intersect)
|
||||
{
|
||||
return { true, gte_c(result.point[0]) };
|
||||
}
|
||||
|
||||
return { false, {} };
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
std::tuple<bool, Vector3<Real>> intersection_ (const Ray3<Real> &ray, const Plane3<Real> &plane)
|
||||
{
|
||||
auto ray_ = gte_c(ray);
|
||||
auto plane_ = gte_c(plane);
|
||||
|
||||
gte::FIQuery<Real, gte::Ray3<Real>, gte::Plane3<Real>> query;
|
||||
auto result = query(ray_, plane_);
|
||||
|
||||
if (result.intersect)
|
||||
{
|
||||
return { true, gte_c(result.point) };
|
||||
}
|
||||
|
||||
return { false, {} };
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
std::tuple<bool, Circle3<Real>> intersection_ (const Sphere3<Real> &l, const Sphere3<Real> &r)
|
||||
{
|
||||
auto l_ = gte_c(l);
|
||||
auto r_ = gte_c(r);
|
||||
|
||||
gte::FIQuery<Real, gte::Sphere3<Real>, gte::Sphere3<Real>> query;
|
||||
auto result = query(l_, r_);
|
||||
|
||||
if (result.intersect)
|
||||
{
|
||||
if (is_in(result.type, 1, 4, 6))
|
||||
{
|
||||
return { true, { gte_c(result.point), math::Vector3<Real>::Zero, 0 } };
|
||||
}
|
||||
return { true, gte_c(result.circle) };
|
||||
}
|
||||
|
||||
return { false, {} };
|
||||
}
|
||||
|
||||
// -------------------
|
||||
|
||||
//template<>
|
||||
//bool intersects (const math::Vector3<r32> &point, const math::Sphere3<r32> &rhs)
|
||||
//{
|
||||
// return intersects_(point, rhs);
|
||||
//}
|
||||
//
|
||||
//template<>
|
||||
//bool intersects (const math::Vector3<r64> &point, const math::Sphere3<r64> &rhs)
|
||||
//{
|
||||
// return intersects_(point, rhs);
|
||||
//}
|
||||
//
|
||||
template<>
|
||||
bool intersects (const math::Sphere3<r32> &sphere, const math::Frustum3<r32> &rhs)
|
||||
{
|
||||
return intersects_(sphere, rhs);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool intersects (const math::Sphere3<r64> &sphere, const math::Frustum3<r64> &rhs)
|
||||
{
|
||||
return intersects_(sphere, rhs);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool intersects (const math::Sphere3<r32> &sphere, const math::Cone3<r32> &rhs)
|
||||
{
|
||||
return intersects_(sphere, rhs);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool intersects (const math::Sphere3<r64> &sphere, const math::Cone3<r64> &rhs)
|
||||
{
|
||||
return intersects_(sphere, rhs);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool intersects (const math::Box3<r32> &lhs, const math::Frustum3<r32> &rhs)
|
||||
{
|
||||
return intersects_(lhs, rhs);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool intersects (const math::Box3<r64> &lhs, const math::Frustum3<r64> &rhs)
|
||||
{
|
||||
return intersects_(lhs, rhs);
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
bool intersects (const math::Vector3<r32> &point, const math::Frustum3<r32> &rhs)
|
||||
{
|
||||
return intersects_(point, rhs);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool intersects (const math::Vector3<r64> &point, const math::Frustum3<r64> &rhs)
|
||||
{
|
||||
return intersects_(point, rhs);
|
||||
}
|
||||
|
||||
//template<>
|
||||
//bool intersects (const math::Segment2<r32> &segment, const math::Circle2<r32> &rhs)
|
||||
//{
|
||||
// return intersects_(segment, rhs);
|
||||
//}
|
||||
//
|
||||
//template<>
|
||||
//bool intersects (const math::Segment2<r64> &segment, const math::Circle2<r64> &rhs)
|
||||
//{
|
||||
// return intersects_(segment, rhs);
|
||||
//}
|
||||
|
||||
template<>
|
||||
std::tuple<bool, math::Vector3<r32>> intersection (const math::Ray3<r32> &ray, const math::Sphere3<r32> &rhs)
|
||||
{
|
||||
return intersection_(ray, rhs);
|
||||
}
|
||||
|
||||
template<>
|
||||
std::tuple<bool, math::Vector3<r64>> intersection (const math::Ray3<r64> &ray, const math::Sphere3<r64> &rhs)
|
||||
{
|
||||
return intersection_(ray, rhs);
|
||||
}
|
||||
|
||||
template<>
|
||||
std::tuple<bool, math::Vector3<r32>> intersection (const math::Ray3<r32> &ray, const math::Plane3<r32> &rhs)
|
||||
{
|
||||
return intersection_(ray, rhs);
|
||||
}
|
||||
|
||||
template<>
|
||||
std::tuple<bool, math::Vector3<r64>> intersection (const math::Ray3<r64> &ray, const math::Plane3<r64> &rhs)
|
||||
{
|
||||
return intersection_(ray, rhs);
|
||||
}
|
||||
|
||||
// ----
|
||||
|
||||
template<>
|
||||
std::tuple<bool, math::Circle3<r32>> intersection (const math::Sphere3<r32> &lhs, const math::Sphere3<r32> &rhs)
|
||||
{
|
||||
return intersection_(lhs, rhs);
|
||||
}
|
||||
|
||||
template<>
|
||||
std::tuple<bool, math::Circle3<r64>> intersection (const math::Sphere3<r64> &lhs, const math::Sphere3<r64> &rhs)
|
||||
{
|
||||
return intersection_(lhs, rhs);
|
||||
}
|
||||
|
||||
|
||||
// ----
|
||||
|
||||
template<typename Real>
|
||||
std::tuple<Real, math::Vector3<Real>> closest_(const math::Ray3<Real> &ray, const math::Vector3<Real> &point)
|
||||
{
|
||||
auto ray_ = gte_c(ray);
|
||||
auto point_ = gte_c(point);
|
||||
|
||||
gte::DCPPoint3Ray3<Real> dcp;
|
||||
auto result = dcp(point_, ray_);
|
||||
|
||||
gte::Vector3<Real> &closest = result.rayClosest;
|
||||
return { result.distance, gte_c(closest) };
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
std::tuple<r64, math::Vector3<r64>> closest(const math::Ray3<r64> &ray, const math::Vector3<r64> &point)
|
||||
{
|
||||
return closest_(ray, point);
|
||||
}
|
||||
|
||||
template<>
|
||||
std::tuple<r32, math::Vector3<r32>> closest(const math::Ray3<r32> &ray, const math::Vector3<r32> &point)
|
||||
{
|
||||
return closest_(ray, point);
|
||||
}
|
||||
|
||||
|
||||
template<typename Real>
|
||||
std::tuple<Real, math::Vector3<Real>> closest_(const math::Segment3<Real> &ray, const math::Vector3<Real> &point)
|
||||
{
|
||||
auto ray_ = gte_c(ray);
|
||||
auto point_ = gte_c(point);
|
||||
|
||||
gte::DCPPoint3Segment3<Real> dcp;
|
||||
auto result = dcp(point_, ray_);
|
||||
|
||||
gte::Vector3<Real> &closest = result.segmentClosest;
|
||||
return { result.distance, gte_c(closest) };
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
std::tuple<r64, math::Vector3<r64>> closest(const math::Segment3<r64> &ray, const math::Vector3<r64> &point)
|
||||
{
|
||||
return closest_(ray, point);
|
||||
}
|
||||
|
||||
template<>
|
||||
std::tuple<r32, math::Vector3<r32>> closest(const math::Segment3<r32> &ray, const math::Vector3<r32> &point)
|
||||
{
|
||||
return closest_(ray, point);
|
||||
}
|
||||
|
||||
// ------------
|
||||
|
||||
template<typename Real>
|
||||
std::tuple<Real, math::Vector3<Real>> closest_(const math::Plane3<Real> &plane, const math::Vector3<Real> &point)
|
||||
{
|
||||
auto plane_ = gte_c(plane);
|
||||
auto point_ = gte_c(point);
|
||||
|
||||
gte::DCPQuery<Real, gte::Vector3<Real>, gte::Plane3<Real>> dcp;
|
||||
auto result = dcp(point_, plane_);
|
||||
|
||||
gte::Vector3<Real> &closest = result.planeClosestPoint;
|
||||
return { result.distance, gte_c(closest) };
|
||||
}
|
||||
|
||||
template<>
|
||||
std::tuple<r64, math::Vector3<r64>> closest(const math::Plane3<r64> &plane, const math::Vector3<r64> &point)
|
||||
{
|
||||
return closest_(plane, point);
|
||||
}
|
||||
|
||||
// ------------
|
||||
|
||||
template<typename Real>
|
||||
Real distance_(const math::Triangle3<Real> &plane, const math::Line3<Real> &line)
|
||||
{
|
||||
auto plane_ = gte_c(plane);
|
||||
auto line_ = gte_c(line);
|
||||
|
||||
gte::DCPQuery<Real, gte::Line3<Real>, gte::Triangle3<Real>> dcp;
|
||||
auto result = dcp(line_, plane_);
|
||||
|
||||
return result.distance;
|
||||
}
|
||||
|
||||
template<>
|
||||
r64 distance(const math::Triangle3<r64> &plane, const math::Line3<r64> &line)
|
||||
{
|
||||
return distance_(plane, line);
|
||||
}
|
||||
|
||||
// ------------
|
||||
|
||||
template<>
|
||||
bool intersects(const math::Triangle3<r64> &plane, const math::Ray3<r64> &line, r64 epsilon)
|
||||
{
|
||||
math::Line3<r64> l = { line.origin, line.direction };
|
||||
return distance(plane, l) < epsilon;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
124
tjp/core/math/Algorithm.h
Executable file
124
tjp/core/math/Algorithm.h
Executable file
@@ -0,0 +1,124 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Math.h"
|
||||
#include "Sphere1.h"
|
||||
#include "Sphere3.h"
|
||||
#include "Vector3.h"
|
||||
#include "Box3.h"
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "Epsilon.h"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
std::tuple<math::Sphere3<Real>, math::Sphere3<Real>> bisectingRegions(const std::vector<math::Vector3<Real>> &points);
|
||||
|
||||
template<typename C, typename D=C>
|
||||
std::tuple<math::Sphere1<C,D>, math::Sphere1<C,D>> bisectingRegions(const std::vector<C> &points);
|
||||
|
||||
|
||||
template<typename Real>
|
||||
math::Sphere3<Real> sphereContaining(const std::vector<math::Vector3<Real>> &spheres, const math::Sphere3<Real> &emptyValue);
|
||||
|
||||
template<typename Real>
|
||||
math::Sphere3<Real> sphereContaining(const std::vector<math::Sphere3<Real>> &spheres, const math::Sphere3<Real> &emptyValue);
|
||||
|
||||
template<typename C, typename D>
|
||||
math::Sphere1<C,D> sphereContaining(const std::vector<math::Sphere1<C,D>> &spheres, const math::Sphere1<C,D> &emptyValue);
|
||||
|
||||
|
||||
template<typename Real, typename T, typename F>
|
||||
math::Sphere3<Real> sphereContaining(const math::Sphere3<Real> &emptyValue, T &t, F &&f);
|
||||
|
||||
template<typename C, typename D, typename T, typename F>
|
||||
math::Sphere1<C,D> sphereContaining(const math::Sphere1<C,D> &emptyValue, T &t, F &&f);
|
||||
|
||||
|
||||
// ---------------------
|
||||
|
||||
template<typename Real>
|
||||
Real distance (const math::Ray3<Real> &ray, const math::Vector3<Real> &r);
|
||||
|
||||
template<typename Real>
|
||||
Real distance (const math::Segment3<Real> &ray, const math::Vector3<Real> &r);
|
||||
|
||||
template<typename Real>
|
||||
bool intersects (const math::Sphere3<Real> &sphere, const math::Cone3<Real> &rhs);
|
||||
|
||||
// ---------------------
|
||||
|
||||
template<typename Real>
|
||||
bool contains (const math::Sphere3<Real> &parent, const math::Sphere3<Real> &child, Real error = epsilon<Real>());
|
||||
|
||||
template<typename C, typename D>
|
||||
bool contains (const math::Sphere1<C,D> &parent, const math::Sphere1<C,D> &child, D error = epsilon<D>());
|
||||
|
||||
// ---------------------
|
||||
|
||||
template<typename Real>
|
||||
bool intersects (const math::Sphere3<Real> &sphere, const math::Sphere3<Real> &rhs, Real error = epsilon<Real>());
|
||||
|
||||
template<typename C, typename D>
|
||||
bool intersects (const math::Sphere1<C,D> &sphere, const math::Sphere1<C,D> &rhs, D error = epsilon<D>());
|
||||
|
||||
template<typename C, typename D>
|
||||
bool intersects (const math::Sphere1<C,D> &sphere, const C &rhs, D error = epsilon<D>());
|
||||
|
||||
template<typename D>
|
||||
bool intersects(const math::Triangle3<D> &plane, const math::Ray3<D> &line, D error = epsilon<D>());
|
||||
|
||||
// ---------------------
|
||||
|
||||
template<typename Real>
|
||||
bool intersects (const math::Vector3<Real> &point, const math::Sphere3<Real> &rhs);
|
||||
|
||||
template<typename Real>
|
||||
bool intersects (const math::Sphere3<Real> &sphere, const math::Frustum3<Real> &rhs);
|
||||
|
||||
template<typename Real>
|
||||
bool intersects (const math::Vector3<Real> &point, const math::Frustum3<Real> &rhs);
|
||||
|
||||
template<typename Real>
|
||||
bool intersects (const math::Box3<Real> &rectangle, const math::Frustum3<Real> &rhs);
|
||||
|
||||
template<typename Real>
|
||||
bool intersects (const math::Segment2<Real> &segment, const math::Circle2<Real> &rhs);
|
||||
|
||||
template<typename Real>
|
||||
std::tuple<bool, math::Vector3<Real>> intersection (const math::Ray3<Real> &ray, const math::Sphere3<Real> &rhs);
|
||||
|
||||
template<typename Real>
|
||||
std::tuple<bool, math::Vector3<Real>> intersection (const math::Ray3<Real> &ray, const math::Plane3<Real> &rhs);
|
||||
|
||||
template<typename Real>
|
||||
std::tuple<Real, math::Vector3<Real>> closest(const math::Ray3<Real> &ray, const math::Vector3<Real> &point);
|
||||
|
||||
template<typename Real>
|
||||
std::tuple<Real, math::Vector3<Real>> closest(const math::Segment3<Real> &ray, const math::Vector3<Real> &point);
|
||||
|
||||
template<typename Real>
|
||||
std::tuple<bool, math::Circle3<Real>> intersection (const math::Sphere3<Real> &ray, const math::Sphere3<Real> &rhs);
|
||||
|
||||
template<typename Real>
|
||||
std::tuple<Real, math::Vector3<Real>> closest(const math::Plane3<Real> &plane, const math::Vector3<Real> &point);
|
||||
|
||||
template<typename Real>
|
||||
Real distance(const math::Triangle3<Real> &plane, const math::Line3<Real> &line);
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
130
tjp/core/math/Algorithm.hpp
Executable file
130
tjp/core/math/Algorithm.hpp
Executable file
@@ -0,0 +1,130 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Algorithm.h"
|
||||
#include "Math.hpp"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<>
|
||||
r32 distance (const math::Ray3<r32> &ray, const math::Vector3<r32> &r);
|
||||
|
||||
template<>
|
||||
r64 distance (const math::Ray3<r64> &ray, const math::Vector3<r64> &r);
|
||||
|
||||
template<>
|
||||
r32 distance (const math::Segment3<r32> &ray, const math::Vector3<r32> &r);
|
||||
|
||||
template<>
|
||||
r64 distance (const math::Segment3<r64> &ray, const math::Vector3<r64> &r);
|
||||
|
||||
template<>
|
||||
std::tuple<math::Sphere3<r32>, math::Sphere3<r32>> bisectingRegions(const std::vector<math::Vector3<r32>> &points);
|
||||
|
||||
template<>
|
||||
std::tuple<math::Sphere3<r64>, math::Sphere3<r64>> bisectingRegions(const std::vector<math::Vector3<r64>> &points);
|
||||
|
||||
|
||||
template<>
|
||||
math::Sphere3<r64> sphereContaining(const std::vector<math::Vector3<r64>> &points, const math::Sphere3<r64> &emptyValue);
|
||||
|
||||
template<>
|
||||
math::Sphere3<r32> sphereContaining(const std::vector<math::Sphere3<r32>> &spheres, const math::Sphere3<r32> &emptyValue);
|
||||
|
||||
template<>
|
||||
math::Sphere3<r64> sphereContaining(const std::vector<math::Sphere3<r64>> &spheres, const math::Sphere3<r64> &emptyValue);
|
||||
|
||||
|
||||
template<>
|
||||
bool intersects (const math::Vector3<r32> &point, const math::Sphere3<r32> &rhs);
|
||||
|
||||
template<>
|
||||
bool intersects (const math::Vector3<r64> &point, const math::Sphere3<r64> &rhs);
|
||||
|
||||
template<>
|
||||
bool intersects (const math::Sphere3<r32> &sphere, const math::Frustum3<r32> &rhs);
|
||||
|
||||
template<>
|
||||
bool intersects (const math::Sphere3<r64> &sphere, const math::Frustum3<r64> &rhs);
|
||||
|
||||
template<>
|
||||
bool intersects (const math::Box3<r32> &rectangle, const math::Frustum3<r32> &rhs);
|
||||
|
||||
template<>
|
||||
bool intersects (const math::Box3<r64> &rectangle, const math::Frustum3<r64> &rhs);
|
||||
|
||||
template<>
|
||||
bool intersects (const math::Vector3<r32> &point, const math::Frustum3<r32> &rhs);
|
||||
|
||||
template<>
|
||||
bool intersects (const math::Vector3<r64> &point, const math::Frustum3<r64> &rhs);
|
||||
|
||||
template<>
|
||||
bool intersects (const math::Sphere3<r64> &sphere, const math::Cone3<r64> &rhs);
|
||||
|
||||
template<>
|
||||
bool intersects (const math::Sphere3<r32> &sphere, const math::Cone3<r32> &rhs);
|
||||
|
||||
template<>
|
||||
bool intersects (const math::Segment2<r32> &segment, const math::Circle2<r32> &rhs);
|
||||
|
||||
template<>
|
||||
bool intersects (const math::Segment2<r64> &segment, const math::Circle2<r64> &rhs);
|
||||
|
||||
template<>
|
||||
std::tuple<bool, math::Vector3<r32>> intersection (const math::Ray3<r32> &ray, const math::Sphere3<r32> &rhs);
|
||||
|
||||
template<>
|
||||
std::tuple<bool, math::Vector3<r64>> intersection (const math::Ray3<r64> &ray, const math::Sphere3<Real> &rhs);
|
||||
|
||||
template<>
|
||||
std::tuple<bool, math::Vector3<r32>> intersection (const math::Ray3<r32> &ray, const math::Plane3<r32> &rhs);
|
||||
|
||||
template<>
|
||||
std::tuple<bool, math::Vector3<r64>> intersection (const math::Ray3<r64> &ray, const math::Plane3<Real> &rhs);
|
||||
|
||||
|
||||
template<>
|
||||
std::tuple<r64, math::Vector3<r64>> closest(const math::Ray3<r64> &ray, const math::Vector3<r64> &point);
|
||||
|
||||
template<>
|
||||
std::tuple<r32, math::Vector3<r32>> closest(const math::Ray3<r32> &ray, const math::Vector3<r32> &point);
|
||||
|
||||
template<>
|
||||
std::tuple<r64, math::Vector3<r64>> closest(const math::Segment3<r64> &ray, const math::Vector3<r64> &point);
|
||||
|
||||
template<>
|
||||
std::tuple<r32, math::Vector3<r32>> closest(const math::Segment3<r32> &ray, const math::Vector3<r32> &point);
|
||||
|
||||
|
||||
template<>
|
||||
std::tuple<bool, math::Circle3<r32>> intersection (const math::Sphere3<r32> &ray, const math::Sphere3<r32> &rhs);
|
||||
|
||||
template<>
|
||||
std::tuple<bool, math::Circle3<r64>> intersection (const math::Sphere3<r64> &ray, const math::Sphere3<r64> &rhs);
|
||||
|
||||
|
||||
template<>
|
||||
std::tuple<r64, math::Vector3<r64>> closest(const math::Plane3<r64> &plane, const math::Vector3<r64> &point);
|
||||
|
||||
template<>
|
||||
r64 distance(const math::Triangle3<r64> &plane, const math::Line3<r64> &line);
|
||||
|
||||
template<>
|
||||
bool intersects(const math::Triangle3<r64> &plane, const math::Ray3<r64> &line, r64 error);
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
#include "Algorithm.inl"
|
||||
77
tjp/core/math/Algorithm.inl
Executable file
77
tjp/core/math/Algorithm.inl
Executable file
@@ -0,0 +1,77 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Algorithm.h"
|
||||
#include "Math.hpp"
|
||||
//#include "BigInt.hpp"
|
||||
//#include "BigDecimal.hpp"
|
||||
|
||||
#include <tjp/core/log/LogOf.h>
|
||||
#include "Vector3.inl"
|
||||
#include "Real.inl"
|
||||
#include "Distance.inl"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename S, typename R>
|
||||
bool intersects_sphere (const S &l, const S &r, R error)
|
||||
{
|
||||
return distance(l.center, r.center) <= (l.radius + r.radius) + error;
|
||||
}
|
||||
|
||||
template<typename S, typename U, typename R>
|
||||
bool intersects_sphere_point (const S &l, const U &r, R error)
|
||||
{
|
||||
return distance(l.center, r) <= (l.radius) + error;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
bool intersects (const math::Sphere3<Real> &l, const math::Sphere3<Real> &r, Real error)
|
||||
{
|
||||
return distance_squared(l.center, r.center) - math::pow2(l.radius + r.radius + error) <= 0;
|
||||
}
|
||||
|
||||
template<typename C, typename D>
|
||||
bool intersects (const math::Sphere1<C,D> &l, const C &r, D error)
|
||||
{
|
||||
return intersects_sphere_point(l, r, error);
|
||||
}
|
||||
|
||||
template<typename C, typename D>
|
||||
bool intersects (const math::Sphere1<C,D> &l, const math::Sphere1<C,D> &r, D error)
|
||||
{
|
||||
return intersects_sphere(l, r, error);
|
||||
}
|
||||
|
||||
template<typename S, typename R>
|
||||
bool contains_sphere (const S &l, const S &r, R error)
|
||||
{
|
||||
return distance(l.center, r.center) + r.radius <= l.radius + error;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
bool contains (const math::Sphere3<Real> &l, const math::Sphere3<Real> &r, Real error)
|
||||
{
|
||||
return contains_sphere(l, r, error);
|
||||
}
|
||||
|
||||
template<typename C, typename D>
|
||||
bool contains (const math::Sphere1<C,D> &l, const math::Sphere1<C,D> &r, D error)
|
||||
{
|
||||
return contains_sphere(l, r, error);
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
27
tjp/core/math/Box3.h
Executable file
27
tjp/core/math/Box3.h
Executable file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Real.h"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
class Box3;
|
||||
|
||||
typedef Box3<float> Box3f;
|
||||
typedef Box3<double> Box3d;
|
||||
typedef Box3<Real> Box3r;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
36
tjp/core/math/Box3.hpp
Executable file
36
tjp/core/math/Box3.hpp
Executable file
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Box3.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
class Box3
|
||||
{
|
||||
public:
|
||||
typedef Real value_type;
|
||||
|
||||
typedef Vector3<Real> Center;
|
||||
Center center;
|
||||
|
||||
using Axis = Vector3<Real>;
|
||||
std::array<Axis, 3> axis;
|
||||
std::array<Real, 3> extent;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
140
tjp/core/math/Distance+BigInt.inl
Executable file
140
tjp/core/math/Distance+BigInt.inl
Executable file
@@ -0,0 +1,140 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Vector3.inl"
|
||||
#include "Vector2.hpp"
|
||||
#include "Vector4.hpp"
|
||||
#include "Real.inl"
|
||||
#include "BigInt.hpp"
|
||||
#include "BigDecimal.hpp"
|
||||
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
inline auto distance_squared(const Vector3<Real> &l, const Vector3<Real> &r)
|
||||
{
|
||||
Real
|
||||
a = r[0] - l[0],
|
||||
b = r[1] - l[1],
|
||||
c = r[2] - l[2];
|
||||
|
||||
return (a*a) + (b*b) + (c*c);
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
inline auto distance_squared(const Vector4<Real> &l, const Vector4<Real> &r)
|
||||
{
|
||||
Real
|
||||
a = r[0] - l[0],
|
||||
b = r[1] - l[1],
|
||||
c = r[2] - l[2],
|
||||
d = r[3] - l[3];
|
||||
|
||||
return (a*a) + (b*b) + (c*c) + (d*d);
|
||||
}
|
||||
|
||||
|
||||
template<typename Real>
|
||||
inline auto distance_squared(const Vector2<Real> &l, const Vector2<Real> &r)
|
||||
{
|
||||
Real
|
||||
a = r[0] - l[0],
|
||||
b = r[1] - l[1];
|
||||
|
||||
return (a*a) + (b*b);
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
inline auto distance_squared(const Vector3<Real> &r, Real x, Real y, Real z)
|
||||
{
|
||||
Real a = r[0] - x;
|
||||
a *= a;
|
||||
|
||||
Real b = r[1] - y;
|
||||
b *= b;
|
||||
|
||||
Real c = r[2] - z;
|
||||
c *= c;
|
||||
|
||||
return a + b + c;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
inline auto distance(const Vector3<Real> &r, Real x, Real y, Real z)
|
||||
{
|
||||
return std::sqrt(distance_squared(r, x, y, z));
|
||||
}
|
||||
|
||||
inline auto distance(const Vector3<r32> &l, const Vector3<r32> &r) { return sqrt(distance_squared(l, r)); }
|
||||
inline auto distance(const Vector3<r64> &l, const Vector3<r64> &r) { return sqrt(distance_squared(l, r)); }
|
||||
|
||||
inline auto distance(const Vector2<r32> &l, const Vector2<r32> &r) { return sqrt(distance_squared(l, r)); }
|
||||
inline auto distance(const Vector2<r64> &l, const Vector2<r64> &r) { return sqrt(distance_squared(l, r)); }
|
||||
|
||||
inline auto distance(const Vector4<r32> &l, const Vector4<r32> &r) { return sqrt(distance_squared(l, r)); }
|
||||
inline auto distance(const Vector4<r64> &l, const Vector4<r64> &r) { return sqrt(distance_squared(l, r)); }
|
||||
|
||||
//
|
||||
|
||||
template<typename V>
|
||||
auto distance_vector_signed(const V &l, const V &r)
|
||||
{
|
||||
return (r-l).length();
|
||||
}
|
||||
|
||||
template<typename V>
|
||||
V distance_integral_unsigned(const V &l, const V &r)
|
||||
{
|
||||
if (r > l)
|
||||
return r - l;
|
||||
|
||||
return l - r;
|
||||
}
|
||||
|
||||
template<typename V>
|
||||
V distance_integral_signed(const V &l, const V &r)
|
||||
{
|
||||
return distance_integral_unsigned(l, r);
|
||||
}
|
||||
|
||||
// ---------------------
|
||||
|
||||
inline auto distance(const Vector3<s32> &l, const Vector3<s32> &r) { return distance_vector_signed(l, r); }
|
||||
inline auto distance(const Vector3<s64> &l, const Vector3<s64> &r) { return distance_vector_signed(l, r); }
|
||||
inline auto distance(const Vector3<s128> &l, const Vector3<s128> &r) { return distance_vector_signed(l, r); }
|
||||
inline auto distance(const Vector3<BigInt> &l, const Vector3<BigInt> &r) { return distance_vector_signed(l, r); }
|
||||
inline auto distance(const Vector3<BigDecimal> &l, const Vector3<BigDecimal> &r) { return distance_vector_signed(l, r); }
|
||||
|
||||
inline auto distance(const r32 &l, const r32 &r) { return distance_integral_signed(l, r); }
|
||||
inline auto distance(const r64 &l, const r64 &r) { return distance_integral_signed(l, r); }
|
||||
inline auto distance(const s32 &l, const s32 &r) { return distance_integral_signed(l, r); }
|
||||
inline auto distance(const s64 &l, const s64 &r) { return distance_integral_signed(l, r); }
|
||||
inline auto distance(const s128 &l, const s128 &r) { return distance_integral_signed(l, r); }
|
||||
|
||||
inline auto distance(const u32 &l, const u32 &r) { return distance_integral_unsigned(l, r); }
|
||||
inline auto distance(const u64 &l, const u64 &r) { return distance_integral_unsigned(l, r); }
|
||||
inline auto distance(const u128 &l, const u128 &r) { return distance_integral_unsigned(l, r); }
|
||||
|
||||
inline auto distance(const BigDecimal &l, const BigDecimal &r) { return distance_integral_signed(l, r); }
|
||||
|
||||
template<typename Real>
|
||||
auto distance_relative(const Real &l, const Real &r)
|
||||
{
|
||||
return distance(l, r);
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
135
tjp/core/math/Distance.inl
Executable file
135
tjp/core/math/Distance.inl
Executable file
@@ -0,0 +1,135 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Vector3.inl"
|
||||
#include "Vector2.hpp"
|
||||
#include "Vector4.hpp"
|
||||
#include "Real.inl"
|
||||
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
inline auto distance_squared(const Vector3<Real> &l, const Vector3<Real> &r)
|
||||
{
|
||||
Real
|
||||
a = r[0] - l[0],
|
||||
b = r[1] - l[1],
|
||||
c = r[2] - l[2];
|
||||
|
||||
return (a*a) + (b*b) + (c*c);
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
inline auto distance_squared(const Vector4<Real> &l, const Vector4<Real> &r)
|
||||
{
|
||||
Real
|
||||
a = r[0] - l[0],
|
||||
b = r[1] - l[1],
|
||||
c = r[2] - l[2],
|
||||
d = r[3] - l[3];
|
||||
|
||||
return (a*a) + (b*b) + (c*c) + (d*d);
|
||||
}
|
||||
|
||||
|
||||
template<typename Real>
|
||||
inline auto distance_squared(const Vector2<Real> &l, const Vector2<Real> &r)
|
||||
{
|
||||
Real
|
||||
a = r[0] - l[0],
|
||||
b = r[1] - l[1];
|
||||
|
||||
return (a*a) + (b*b);
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
inline auto distance_squared(const Vector3<Real> &r, Real x, Real y, Real z)
|
||||
{
|
||||
Real a = r[0] - x;
|
||||
a *= a;
|
||||
|
||||
Real b = r[1] - y;
|
||||
b *= b;
|
||||
|
||||
Real c = r[2] - z;
|
||||
c *= c;
|
||||
|
||||
return a + b + c;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
inline auto distance(const Vector3<Real> &r, Real x, Real y, Real z)
|
||||
{
|
||||
return std::sqrt(distance_squared(r, x, y, z));
|
||||
}
|
||||
|
||||
inline auto distance(const Vector3<r32> &l, const Vector3<r32> &r) { return sqrt(distance_squared(l, r)); }
|
||||
inline auto distance(const Vector3<r64> &l, const Vector3<r64> &r) { return sqrt(distance_squared(l, r)); }
|
||||
|
||||
inline auto distance(const Vector2<r32> &l, const Vector2<r32> &r) { return sqrt(distance_squared(l, r)); }
|
||||
inline auto distance(const Vector2<r64> &l, const Vector2<r64> &r) { return sqrt(distance_squared(l, r)); }
|
||||
|
||||
inline auto distance(const Vector4<r32> &l, const Vector4<r32> &r) { return sqrt(distance_squared(l, r)); }
|
||||
inline auto distance(const Vector4<r64> &l, const Vector4<r64> &r) { return sqrt(distance_squared(l, r)); }
|
||||
|
||||
//
|
||||
|
||||
template<typename V>
|
||||
auto distance_vector_signed(const V &l, const V &r)
|
||||
{
|
||||
return (r-l).length();
|
||||
}
|
||||
|
||||
template<typename V>
|
||||
V distance_integral_unsigned(const V &l, const V &r)
|
||||
{
|
||||
if (r > l)
|
||||
return r - l;
|
||||
|
||||
return l - r;
|
||||
}
|
||||
|
||||
template<typename V>
|
||||
V distance_integral_signed(const V &l, const V &r)
|
||||
{
|
||||
return distance_integral_unsigned(l, r);
|
||||
}
|
||||
|
||||
// ---------------------
|
||||
|
||||
inline auto distance(const Vector3<s32> &l, const Vector3<s32> &r) { return distance_vector_signed(l, r); }
|
||||
inline auto distance(const Vector3<s64> &l, const Vector3<s64> &r) { return distance_vector_signed(l, r); }
|
||||
inline auto distance(const Vector3<s128> &l, const Vector3<s128> &r) { return distance_vector_signed(l, r); }
|
||||
|
||||
inline auto distance(const r32 &l, const r32 &r) { return distance_integral_signed(l, r); }
|
||||
inline auto distance(const r64 &l, const r64 &r) { return distance_integral_signed(l, r); }
|
||||
inline auto distance(const s32 &l, const s32 &r) { return distance_integral_signed(l, r); }
|
||||
inline auto distance(const s64 &l, const s64 &r) { return distance_integral_signed(l, r); }
|
||||
inline auto distance(const s128 &l, const s128 &r) { return distance_integral_signed(l, r); }
|
||||
|
||||
inline auto distance(const u32 &l, const u32 &r) { return distance_integral_unsigned(l, r); }
|
||||
inline auto distance(const u64 &l, const u64 &r) { return distance_integral_unsigned(l, r); }
|
||||
inline auto distance(const u128 &l, const u128 &r) { return distance_integral_unsigned(l, r); }
|
||||
|
||||
|
||||
template<typename Real>
|
||||
auto distance_relative(const Real &l, const Real &r)
|
||||
{
|
||||
return distance(l, r);
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
69
tjp/core/math/Epsilon.h
Executable file
69
tjp/core/math/Epsilon.h
Executable file
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tjp/core/types/Types.h>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename T>
|
||||
T epsilon()
|
||||
{
|
||||
return T(0.00001);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline
|
||||
s128 epsilon()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline
|
||||
s64 epsilon()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline
|
||||
s32 epsilon()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline
|
||||
u128 epsilon()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline
|
||||
u64 epsilon()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline
|
||||
u32 epsilon()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
25
tjp/core/math/Eulers.h
Executable file
25
tjp/core/math/Eulers.h
Executable file
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
struct Eulers;
|
||||
|
||||
typedef Eulers<double> Eulersd;
|
||||
typedef Eulers<float> Eulersf;
|
||||
typedef Eulers<Real> Eulersr;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
40
tjp/core/math/Eulers.hpp
Executable file
40
tjp/core/math/Eulers.hpp
Executable file
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Eulers.h"
|
||||
#include "Zero.h"
|
||||
#include <tjp/core/types/Types.h>
|
||||
#include <tjp/core/containers/Pack.h>
|
||||
|
||||
#include <tjp/core/assert/debug_assert.h>
|
||||
#include <initializer_list>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
struct Eulers {
|
||||
Real pitch, yaw, roll;
|
||||
} ;
|
||||
|
||||
template<typename Real>
|
||||
bool operator ==(const Eulers<Real> &lhs, const Eulers<Real> &rhs)
|
||||
{
|
||||
return
|
||||
lhs.pitch == rhs.pitch &&
|
||||
lhs.yaw == rhs.yaw &&
|
||||
lhs.roll == rhs.roll;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
20
tjp/core/math/FastFourier.h
Executable file
20
tjp/core/math/FastFourier.h
Executable file
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
// https://rosettacode.org/wiki/Fast_Fourier_transform
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
135
tjp/core/math/FloatPack.inl
Executable file
135
tjp/core/math/FloatPack.inl
Executable file
@@ -0,0 +1,135 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Vector2.inl"
|
||||
#include "Vector3.inl"
|
||||
#include "Vector4.inl"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
constexpr int float_2_bits = 12;
|
||||
constexpr int float_3_bits = 8;
|
||||
constexpr int float_4_bits = 6;
|
||||
|
||||
const float float_2_max = 1 << float_2_bits;
|
||||
const Vector2f float_2_decoder = { 1, (1<<float_2_bits) };
|
||||
const Vector2f float_2_encoder = 1/float_2_decoder;
|
||||
|
||||
Vector2f unpack2u(r32 v)
|
||||
{
|
||||
auto a = float_2_decoder * v;
|
||||
auto b = fract(a);
|
||||
auto c = trunc(b * float_2_max) / float_2_max;
|
||||
return c;
|
||||
}
|
||||
|
||||
r32 pack2u (Vector2f v)
|
||||
{
|
||||
auto a = trunc(v * float_2_max);
|
||||
auto b = a / float_2_max;
|
||||
auto c = dot(b, float_2_encoder);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
Vector2f unpack2s(r32 v)
|
||||
{
|
||||
return 2.0f * unpack2u(v) - Vector2f { 1, 1 };
|
||||
}
|
||||
|
||||
r32 pack2s (Vector2f v)
|
||||
{
|
||||
return pack2u(0.5f * (v + Vector2f { 1, 1 }));
|
||||
}
|
||||
|
||||
const float float_4_max = 1 << float_4_bits;
|
||||
|
||||
const Vector4f float_4_decoder = {
|
||||
1,
|
||||
(1<<float_4_bits),
|
||||
(1<<(2*float_4_bits)),
|
||||
(1<<(3*float_4_bits))
|
||||
};
|
||||
|
||||
const Vector4f float_4_encoder = 1/float_4_decoder;
|
||||
|
||||
Vector4f unpack4u(r32 v)
|
||||
{
|
||||
auto a = float_4_decoder * v;
|
||||
auto b = fract(a);
|
||||
auto c = trunc(b * float_4_max);
|
||||
auto d = c / float_4_max;
|
||||
return d;
|
||||
}
|
||||
|
||||
r32 pack4u (Vector4f v)
|
||||
{
|
||||
auto a = trunc(v * float_4_max);
|
||||
auto b = a / float_4_max;
|
||||
auto c = dot(b, float_4_encoder);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
Vector4f unpack4s(r32 v)
|
||||
{
|
||||
return 2.0f * unpack4u(v) - Vector4f { 1, 1, 1, 1 };
|
||||
}
|
||||
|
||||
r32 pack4s (Vector4f v)
|
||||
{
|
||||
return pack4u(0.5f * (v + Vector4f { 1, 1, 1, 1 }));
|
||||
}
|
||||
|
||||
|
||||
const float float_3_max = 1 << float_3_bits;
|
||||
|
||||
const Vector3f float_3_decoder = {
|
||||
1,
|
||||
(1<<float_3_bits),
|
||||
(1<<(2*float_3_bits))
|
||||
} ;
|
||||
|
||||
const Vector3f float_3_encoder = 1/float_3_decoder;
|
||||
|
||||
Vector3f unpack3u(r32 v)
|
||||
{
|
||||
auto a = float_3_decoder * v;
|
||||
auto b = fract(a);
|
||||
auto c = trunc(b * float_3_max);
|
||||
auto d = c / float_3_max;
|
||||
return d;
|
||||
}
|
||||
|
||||
r32 pack3u (Vector3f v)
|
||||
{
|
||||
auto a = trunc(v * float_3_max);
|
||||
auto b = a / float_3_max;
|
||||
auto c = dot(b, float_3_encoder);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
Vector3f unpack3s(r32 v)
|
||||
{
|
||||
return 2.0f * unpack3u(v) - Vector3f { 1, 1, 1 };
|
||||
}
|
||||
|
||||
r32 pack3s (Vector3f v)
|
||||
{
|
||||
return pack3u(0.5f * (v + Vector3f { 1, 1, 1 }));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
188
tjp/core/math/GTE_convert.hpp
Executable file
188
tjp/core/math/GTE_convert.hpp
Executable file
@@ -0,0 +1,188 @@
|
||||
//
|
||||
// Math.cpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#include "Algorithm.h"
|
||||
#include "Math.hpp"
|
||||
|
||||
#include "Box3.hpp"
|
||||
|
||||
#include <Mathematics/Vector3.h>
|
||||
#include <Mathematics/Circle3.h>
|
||||
#include <Mathematics/Frustum3.h>
|
||||
#include <Mathematics/Segment.h>
|
||||
#include <Mathematics/Ray.h>
|
||||
#include <Mathematics/Triangle.h>
|
||||
#include <Mathematics/Hypersphere.h>
|
||||
#include <Mathematics/Hyperplane.h>
|
||||
#include <Mathematics/Cone.h>
|
||||
#include <Mathematics/Line.h>
|
||||
#include <Mathematics/OrientedBox.h>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
Vector3<Real> gte_c (const gte::Vector3<Real> &v)
|
||||
{
|
||||
return { v[0], v[1], v[2] };
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
gte::Vector3<Real> gte_c (const Vector3<Real> &v)
|
||||
{
|
||||
return { v[0], v[1], v[2] };
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Circle2<Real> gte_c (const gte::Circle2<Real> &v)
|
||||
{
|
||||
return { gte_c(v.center), v.radius };
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
gte::Circle2<Real> gte_c (const Circle2<Real> &v)
|
||||
{
|
||||
return { gte_c(v.center), v.radius };
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Circle3<Real> gte_c (const gte::Circle3<Real> &v)
|
||||
{
|
||||
return { gte_c(v.center), gte_c(v.normal), v.radius };
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
gte::Circle3<Real> gte_c (const Circle3<Real> &v)
|
||||
{
|
||||
return { gte_c(v.center), gte_c(v.normal), v.radius };
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Sphere3<Real> gte_c (const gte::Sphere3<Real> &v)
|
||||
{
|
||||
return { gte_c(v.center), v.radius };
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
gte::Sphere3<Real> gte_c (const Sphere3<Real> &v)
|
||||
{
|
||||
return { gte_c(v.center), v.radius };
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
gte::OrientedBox<3, Real> gte_c (const Box3<Real> &v)
|
||||
{
|
||||
return {
|
||||
gte_c(v.center),
|
||||
{
|
||||
gte_c(v.axis[0]),
|
||||
gte_c(v.axis[1]),
|
||||
gte_c(v.axis[2])
|
||||
},
|
||||
v.extent
|
||||
};
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Box3<Real> gte_c (const gte::OrientedBox<3, Real> &v)
|
||||
{
|
||||
return {
|
||||
gte_c(v.center),
|
||||
{
|
||||
gte_c(v.axis[0]),
|
||||
gte_c(v.axis[1]),
|
||||
gte_c(v.axis[2])
|
||||
},
|
||||
v.extent
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename Real>
|
||||
gte::Plane3<Real> gte_c (const Plane3<Real> &v)
|
||||
{
|
||||
return { gte_c(v.normal), v.constant };
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
gte::Frustum3<Real> gte_c (const Frustum3<Real> &v)
|
||||
{
|
||||
return {
|
||||
gte_c(v.origin),
|
||||
gte_c(v.dVector),
|
||||
gte_c(v.uVector),
|
||||
gte_c(v.rVector),
|
||||
v.dMin, v.dMax, v.uBound, v.rBound
|
||||
};
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
gte::Cone3<Real> gte_c (const Cone3<Real> &v)
|
||||
{
|
||||
return {
|
||||
gte_c(v.ray),
|
||||
v.angle
|
||||
};
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
gte::Triangle3<Real> gte_c (const Triangle3<Real> &v)
|
||||
{
|
||||
return {
|
||||
gte_c(v.v[0]),
|
||||
gte_c(v.v[1]),
|
||||
gte_c(v.v[2])
|
||||
};
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Triangle3<Real> gte_c (const gte::Triangle3<Real> &v)
|
||||
{
|
||||
return {
|
||||
gte_c(v.v[0]),
|
||||
gte_c(v.v[1]),
|
||||
gte_c(v.v[2])
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
template<typename Real>
|
||||
gte::Line3<Real> gte_c (const Line3<Real> &v)
|
||||
{
|
||||
return {
|
||||
gte_c(v.origin),
|
||||
gte_c(v.direction)
|
||||
};
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Line3<Real> gte_c (const gte::Line3<Real> &v)
|
||||
{
|
||||
return {
|
||||
gte_c(v.origin),
|
||||
gte_c(v.direction)
|
||||
};
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
gte::Ray3<Real> gte_c (const Ray3<Real> &v)
|
||||
{
|
||||
return { gte_c(v.origin), gte_c(v.direction) };
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
gte::Segment3<Real> gte_c (const Segment3<Real> &v)
|
||||
{
|
||||
return { gte_c(v.begin), gte_c(v.end) };
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
56
tjp/core/math/HMatrix.cpp
Executable file
56
tjp/core/math/HMatrix.cpp
Executable file
@@ -0,0 +1,56 @@
|
||||
//
|
||||
// Math.cpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#include "HMatrix.hpp"
|
||||
#include "HMatrix.inl"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
// inline
|
||||
template<>
|
||||
HMatrix<double> operator *(const HMatrix<double> &lhs, const HMatrix<double> &rhs)
|
||||
{
|
||||
HMatrix<Real> result;
|
||||
|
||||
for (int r = 0; r < 4; ++r)
|
||||
{
|
||||
for (int c = 0; c < 4; ++c)
|
||||
{
|
||||
result[r][c] = 0;
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
result[r][c] += lhs[i][c] * rhs[r][i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
const HMatrix<double> HMatrix<double>::Zero {
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0
|
||||
};
|
||||
|
||||
template<>
|
||||
const HMatrix<double> HMatrix<double>::Identity {
|
||||
1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1
|
||||
};
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
27
tjp/core/math/HMatrix.h
Executable file
27
tjp/core/math/HMatrix.h
Executable file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Real.h"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
class HMatrix;
|
||||
|
||||
typedef HMatrix<Real> HMatrixr;
|
||||
typedef HMatrix<float> HMatrixf;
|
||||
typedef HMatrix<double> HMatrixd;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
78
tjp/core/math/HMatrix.hpp
Executable file
78
tjp/core/math/HMatrix.hpp
Executable file
@@ -0,0 +1,78 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "HMatrix.h"
|
||||
#include "Matrix3.h"
|
||||
#include "Vector3.h"
|
||||
|
||||
#include <initializer_list>
|
||||
#include <tjp/core/types/Types.h>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
class HMatrix
|
||||
{
|
||||
public:
|
||||
typedef Real value_type;
|
||||
|
||||
Real v[16];
|
||||
|
||||
public:
|
||||
HMatrix<Real>(std::initializer_list<Real> l);
|
||||
HMatrix<Real>(const Matrix3<Real> &m, const Vector3<Real> &t, const Vector3<Real> &s);
|
||||
HMatrix<Real>() {}
|
||||
|
||||
const Real* operator[] (size_t row) const;
|
||||
Real* operator[] (size_t row);
|
||||
|
||||
static const HMatrix<Real> Zero;
|
||||
static const HMatrix<Real> Identity;
|
||||
|
||||
template<typename U>
|
||||
HMatrix<U> asType() const
|
||||
{
|
||||
return HMatrix<U> {
|
||||
(U)v[0], (U)v[1], (U)v[2], (U)v[3],
|
||||
(U)v[4], (U)v[5], (U)v[6], (U)v[7],
|
||||
(U)v[8], (U)v[9], (U)v[10], (U)v[11],
|
||||
(U)v[12], (U)v[13], (U)v[14], (U)v[15],
|
||||
};
|
||||
}
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
template<typename Real>
|
||||
const HMatrix<Real> HMatrix<Real>::Zero = {
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0
|
||||
};
|
||||
|
||||
template<typename Real>
|
||||
const HMatrix<Real> HMatrix<Real>::Identity = {
|
||||
1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1
|
||||
};
|
||||
|
||||
typedef HMatrix<Real> HMatrixr;
|
||||
typedef HMatrix<float> HMatrixf;
|
||||
typedef HMatrix<double> HMatrixd;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
128
tjp/core/math/HMatrix.inl
Executable file
128
tjp/core/math/HMatrix.inl
Executable file
@@ -0,0 +1,128 @@
|
||||
//
|
||||
// Math.inl
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "HMatrix.hpp"
|
||||
#include "HPoint.hpp"
|
||||
#include "Zero.h"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
HMatrix<Real>::HMatrix(std::initializer_list<Real> l)
|
||||
{
|
||||
int i=0;
|
||||
for (auto &r : l)
|
||||
v[i++] = r;
|
||||
}
|
||||
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
HMatrix<Real>::HMatrix (const Matrix3<Real> &m, const Vector3<Real> &t, const Vector3<Real> &s)
|
||||
{
|
||||
Real vn[] {
|
||||
m.v[0] * s[0], m.v[1] * s[1], m.v[2] * s[2], t[0],
|
||||
m.v[3] * s[0], m.v[4] * s[1], m.v[5] * s[2], t[1],
|
||||
m.v[6] * s[0], m.v[7] * s[1], m.v[8] * s[2], t[2],
|
||||
0, 0, 0, 1
|
||||
};
|
||||
|
||||
for (int i=0; i<16; ++i)
|
||||
v[i] = vn[i];
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
HMatrix<Real> operator *(const HMatrix<Real> &lhs, const HMatrix<Real> &rhs);
|
||||
|
||||
template<>
|
||||
HMatrix<double> operator *(const HMatrix<double> &lhs, const HMatrix<double> &rhs);
|
||||
|
||||
template<typename Real>
|
||||
Vector3<Real> operator *(const HMatrix<Real> &hm, const Vector3<Real> &p)
|
||||
{
|
||||
HPoint<Real> hp(p);
|
||||
auto v = hm * hp;
|
||||
return { v.v[0], v.v[1], v.v[2] };
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
HPoint<Real> operator *(const HMatrix<Real> &m, const HPoint<Real> &p)
|
||||
{
|
||||
return HPoint<Real>(
|
||||
m.v[ 0]*p[0] +
|
||||
m.v[ 1]*p[1] +
|
||||
m.v[ 2]*p[2] +
|
||||
m.v[ 3]*p[3],
|
||||
|
||||
m.v[ 4]*p[0] +
|
||||
m.v[ 5]*p[1] +
|
||||
m.v[ 6]*p[2] +
|
||||
m.v[ 7]*p[3],
|
||||
|
||||
m.v[ 8]*p[0] +
|
||||
m.v[ 9]*p[1] +
|
||||
m.v[10]*p[2] +
|
||||
m.v[11]*p[3],
|
||||
|
||||
m.v[12]*p[0] +
|
||||
m.v[13]*p[1] +
|
||||
m.v[14]*p[2] +
|
||||
m.v[15]*p[3]);
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
HPoint<Real> operator* (const HPoint<Real>& p, const HMatrix<Real>& mat)
|
||||
{
|
||||
return HPoint<Real>(
|
||||
p[0]*mat[0][0] + p[1]*mat[1][0] + p[2]*mat[2][0] + p[3]*mat[3][0],
|
||||
p[0]*mat[0][1] + p[1]*mat[1][1] + p[2]*mat[2][1] + p[3]*mat[3][1],
|
||||
p[0]*mat[0][2] + p[1]*mat[1][2] + p[2]*mat[2][2] + p[3]*mat[3][2],
|
||||
p[0]*mat[0][3] + p[1]*mat[1][3] + p[2]*mat[2][3] + p[3]*mat[3][3]);
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
const Real* HMatrix<Real>::operator[] (size_t row) const
|
||||
{
|
||||
return &v[4*row];
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Real* HMatrix<Real>::operator[] (size_t row)
|
||||
{
|
||||
return &v[4*row];
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
bool operator ==(const HMatrix<Real> &lhs, const HMatrix<Real> &rhs)
|
||||
{
|
||||
for (auto i=0; i<16; ++i)
|
||||
if (lhs.v[i] != rhs.v[i])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
bool operator !=(const HMatrix<Real> &lhs, const HMatrix<Real> &rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
27
tjp/core/math/HPoint.h
Executable file
27
tjp/core/math/HPoint.h
Executable file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Real.h"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
struct HPoint;
|
||||
|
||||
typedef HPoint<Real> HPointr;
|
||||
typedef HPoint<float> HPointf;
|
||||
typedef HPoint<double> HPointd;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
44
tjp/core/math/HPoint.hpp
Executable file
44
tjp/core/math/HPoint.hpp
Executable file
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "HPoint.h"
|
||||
#include "Vector3.h"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
struct HPoint
|
||||
{
|
||||
typedef Real value_type;
|
||||
|
||||
Real v[4];
|
||||
|
||||
HPoint();
|
||||
|
||||
HPoint(const Vector3<Real> &r);
|
||||
HPoint(Real v0, Real v1, Real v2, Real v3);
|
||||
|
||||
Real &operator[](size_t size);
|
||||
Real const &operator[](size_t size) const;
|
||||
|
||||
operator Vector3<Real>&();
|
||||
operator const Vector3<Real>&() const;
|
||||
};
|
||||
|
||||
typedef HPoint<Real> HPointr;
|
||||
typedef HPoint<float> HPointf;
|
||||
typedef HPoint<double> HPointd;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
74
tjp/core/math/HPoint.inl
Executable file
74
tjp/core/math/HPoint.inl
Executable file
@@ -0,0 +1,74 @@
|
||||
//
|
||||
// Math.inl
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "HPoint.hpp"
|
||||
#include "Zero.h"
|
||||
#include "Vector3.hpp"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
|
||||
template<typename Real>
|
||||
HPoint<Real>::HPoint ()
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
HPoint<Real>::HPoint(Real v0, Real v1, Real v2, Real v3)
|
||||
{
|
||||
v[0] = v0;
|
||||
v[1] = v1;
|
||||
v[2] = v2;
|
||||
v[3] = v3;
|
||||
}
|
||||
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
HPoint<Real>::HPoint(const Vector3<Real> &r)
|
||||
{
|
||||
v[0] = r.v[0];
|
||||
v[1] = r.v[1];
|
||||
v[2] = r.v[2];
|
||||
v[3] = 1;
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
HPoint<Real>::operator Vector3<Real>&()
|
||||
{
|
||||
return *(Vector3<Real> *)this;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
HPoint<Real>::operator const Vector3<Real>&() const
|
||||
{
|
||||
return *(const Vector3<Real> *)this;
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Real &HPoint<Real>::operator[](size_t size)
|
||||
{
|
||||
return v[size];
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Real const &HPoint<Real>::operator[](size_t size) const
|
||||
{
|
||||
return v[size];
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
259
tjp/core/math/Math+IO.h
Normal file
259
tjp/core/math/Math+IO.h
Normal file
@@ -0,0 +1,259 @@
|
||||
//
|
||||
// MathIO.h
|
||||
// common
|
||||
//
|
||||
// Created by Timothy Prepscius on 8/4/18.
|
||||
// Copyright © 2018 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Math.h"
|
||||
#include <tjp/core/io/bin/IO.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "Matrix3.hpp"
|
||||
#include "HMatrix.hpp"
|
||||
#include "HPoint.hpp"
|
||||
#include "Vector3.hpp"
|
||||
#include "Sphere3.hpp"
|
||||
#include "Sphere1.hpp"
|
||||
#include "Segment1.hpp"
|
||||
#include "Vector4.hpp"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename T>
|
||||
std::ostream &operator <<(std::ostream &o, const HMatrix<T> &v)
|
||||
{
|
||||
for (auto i=0; i<4; ++i)
|
||||
{
|
||||
o << "[";
|
||||
o << v[i][0];
|
||||
for (auto j=1; j<4; ++j)
|
||||
{
|
||||
o << ",";
|
||||
o << v[i][j];
|
||||
}
|
||||
o << "]";
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream &operator <<(std::ostream &o, const Vector3<T> &v)
|
||||
{
|
||||
o << v[0];
|
||||
for (auto j=1; j<3; ++j)
|
||||
{
|
||||
o << ",";
|
||||
o << v[j];
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream &operator <<(std::ostream &o, const Vector4<T> &v)
|
||||
{
|
||||
o << v[0];
|
||||
for (auto j=1; j<4; ++j)
|
||||
{
|
||||
o << ",";
|
||||
o << v[j];
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream &operator <<(std::ostream &o, const HPoint<T> &v)
|
||||
{
|
||||
o << "(";
|
||||
o << v[0];
|
||||
for (auto j=1; j<4; ++j)
|
||||
{
|
||||
o << ",";
|
||||
o << v[j];
|
||||
}
|
||||
o << ")";
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream &operator <<(std::ostream &o, const Vector2<T> &v)
|
||||
{
|
||||
o << v[0];
|
||||
for (auto j=1; j<2; ++j)
|
||||
{
|
||||
o << ",";
|
||||
o << v[j];
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
std::ostream &operator <<(std::ostream &o, const Matrix3<T> &v)
|
||||
{
|
||||
for (auto i=0; i<3; ++i)
|
||||
{
|
||||
o << "[";
|
||||
o << v[i][0];
|
||||
for (auto j=1; j<3; ++j)
|
||||
{
|
||||
o << ",";
|
||||
o << v[i][j];
|
||||
}
|
||||
o << "]";
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream &operator <<(std::ostream &o, const Sphere3<T> &v)
|
||||
{
|
||||
o << "{" << v.center << ":" << v.radius << "}";
|
||||
return o;
|
||||
}
|
||||
|
||||
template<typename C, typename D>
|
||||
std::ostream &operator <<(std::ostream &o, const Sphere1<C, D> &v)
|
||||
{
|
||||
o << "{" << v.center << ":" << v.radius << "}";
|
||||
return o;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream &operator <<(std::ostream &o, const Segment1<T> &v)
|
||||
{
|
||||
o << "{" << v.begin << "," << v.end << "}";
|
||||
return o;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------
|
||||
|
||||
template<typename IO, typename R>
|
||||
void io_(IO &io, math::Vector2<R> &m)
|
||||
{
|
||||
io.array(m.v[0], m.v[1]);
|
||||
}
|
||||
|
||||
template<typename IO, typename R>
|
||||
void io_(IO &io, math::Vector3<R> &m)
|
||||
{
|
||||
io.array(m.v[0], m.v[1], m.v[2]);
|
||||
}
|
||||
|
||||
template<typename IO, typename R>
|
||||
void io_(IO &io, math::Vector4<R> &m)
|
||||
{
|
||||
io.array(m.v[0], m.v[1], m.v[2], m.v[3]);
|
||||
}
|
||||
|
||||
template<typename IO, typename R>
|
||||
void io_(IO &io, math::Plane3<R> &m)
|
||||
{
|
||||
io.object("normal", m.normal, "constant", m.constant);
|
||||
}
|
||||
|
||||
template<typename IO, typename R>
|
||||
void io_(IO &io, math::Sphere3<R> &m)
|
||||
{
|
||||
io.object("center", m.center, "radius", m.radius);
|
||||
}
|
||||
|
||||
template<typename IO, typename C, typename D>
|
||||
void io_(IO &io, math::Sphere1<C, D> &m)
|
||||
{
|
||||
io.object("center", m.center, "radius", m.radius);
|
||||
}
|
||||
|
||||
template<typename IO, typename R>
|
||||
void io_(IO &io, math::Segment1<R> &m)
|
||||
{
|
||||
io.object("begin", m.begin, "end", m.end);
|
||||
}
|
||||
|
||||
template<typename IO, typename R>
|
||||
void io_(IO &io, math::HMatrix<R> &m)
|
||||
{
|
||||
io.array(
|
||||
m.v[0], m.v[1], m.v[2], m.v[3],
|
||||
m.v[4], m.v[5], m.v[6], m.v[7],
|
||||
m.v[8], m.v[9], m.v[10], m.v[11],
|
||||
m.v[12], m.v[13], m.v[14], m.v[15]
|
||||
);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------
|
||||
|
||||
template<typename IO, typename R>
|
||||
void io_bin(IO &io, math::Vector2<R> &m) { return io_(io, m); }
|
||||
|
||||
template<typename IO, typename R>
|
||||
void io_json(IO &io, math::Vector2<R> &m) { return io_(io, m); }
|
||||
|
||||
|
||||
template<typename IO, typename R>
|
||||
void io_bin(IO &io, math::Vector3<R> &m) { return io_(io, m); }
|
||||
|
||||
template<typename IO, typename R>
|
||||
void io_json(IO &io, math::Vector3<R> &m) { return io_(io, m); }
|
||||
|
||||
|
||||
template<typename IO, typename R>
|
||||
void io_bin(IO &io, math::Vector4<R> &m) { return io_(io, m); }
|
||||
|
||||
template<typename IO, typename R>
|
||||
void io_json(IO &io, math::Vector4<R> &m) { return io_(io, m); }
|
||||
|
||||
|
||||
template<typename IO, typename R>
|
||||
void io_bin(IO &io, math::Plane3<R> &m) { return io_(io, m); }
|
||||
|
||||
template<typename IO, typename R>
|
||||
void io_json(IO &io, math::Plane3<R> &m) { return io_(io, m); }
|
||||
|
||||
|
||||
template<typename IO, typename C, typename D>
|
||||
void io_bin(IO &io, math::Sphere1<C, D> &m) { return io_(io, m); }
|
||||
|
||||
template<typename IO, typename C, typename D>
|
||||
void io_json(IO &io, math::Sphere1<C, D> &m) { return io_(io, m); }
|
||||
|
||||
|
||||
template<typename IO, typename R>
|
||||
void io_bin(IO &io, math::Segment1<R> &m) { return io_(io, m); }
|
||||
|
||||
template<typename IO, typename R>
|
||||
void io_json(IO &io, math::Segment1<R> &m) { return io_(io, m); }
|
||||
|
||||
|
||||
template<typename IO, typename R>
|
||||
void io_bin(IO &io, math::Sphere3<R> &m) { return io_(io, m); }
|
||||
|
||||
template<typename IO, typename R>
|
||||
void io_json(IO &io, math::Sphere3<R> &m) { return io_(io, m); }
|
||||
|
||||
|
||||
template<typename IO, typename R>
|
||||
void io_bin(IO &io, math::HMatrix<R> &m) { return io_(io, m); }
|
||||
|
||||
template<typename IO, typename R>
|
||||
void io_json(IO &io, math::HMatrix<R> &m) { return io_(io, m); }
|
||||
|
||||
|
||||
// ----------------------------------------------------
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
28
tjp/core/math/Math+V.h
Normal file
28
tjp/core/math/Math+V.h
Normal file
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// MathIO.h
|
||||
// common
|
||||
//
|
||||
// Created by Timothy Prepscius on 8/4/18.
|
||||
// Copyright © 2018 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Math.h"
|
||||
#include <tjp/core/variant/VType.h>
|
||||
|
||||
#include "Vector3.h"
|
||||
#include "Vector2.h"
|
||||
#include "Sphere3.h"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
extern const VType Vector3r_vtype;
|
||||
extern const VType Sphere3s16_vtype;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
89
tjp/core/math/Math.h
Executable file
89
tjp/core/math/Math.h
Executable file
@@ -0,0 +1,89 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Real.h"
|
||||
#
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
struct constants;
|
||||
|
||||
template<typename Real>
|
||||
struct Ray3;
|
||||
|
||||
template<typename Real>
|
||||
struct Segment3;
|
||||
|
||||
template<typename Real>
|
||||
struct Line3;
|
||||
|
||||
template<typename Real>
|
||||
class Plane3;
|
||||
|
||||
template<typename Real>
|
||||
class Cone3;
|
||||
|
||||
template<typename Real>
|
||||
class Frustum3;
|
||||
|
||||
template<typename Real>
|
||||
struct Box3;
|
||||
|
||||
template<typename Real>
|
||||
struct Segment2;
|
||||
|
||||
template<typename Real>
|
||||
class Circle2;
|
||||
|
||||
template<typename Real>
|
||||
class Circle3;
|
||||
|
||||
template<typename Real>
|
||||
class Triangle3;
|
||||
|
||||
typedef Ray3<double> Ray3d;
|
||||
typedef Ray3<float> Ray3f;
|
||||
typedef Ray3<Real> Ray3r;
|
||||
|
||||
typedef Segment2<double> Segment2d;
|
||||
typedef Segment2<float> Segment2f;
|
||||
typedef Segment2<Real> Segment2r;
|
||||
|
||||
typedef Circle2<double> Circle2d;
|
||||
typedef Circle2<float> Circle2f;
|
||||
typedef Circle2<Real> Circle2r;
|
||||
|
||||
typedef Line3<double> Line3d;
|
||||
typedef Line3<float> Line3f;
|
||||
typedef Line3<Real> Line3r;
|
||||
|
||||
typedef Plane3<float> Plane3f;
|
||||
typedef Plane3<double> Plane3d;
|
||||
typedef Plane3<Real> Plane3r;
|
||||
|
||||
typedef Triangle3<float> Triangle3f;
|
||||
typedef Triangle3<double> Triangle3d;
|
||||
typedef Triangle3<Real> Triangle3r;
|
||||
|
||||
typedef Cone3<float> Cone3f;
|
||||
typedef Cone3<double> Cone3d;
|
||||
typedef Cone3<Real> Cone3r;
|
||||
|
||||
typedef Frustum3<double> Frustum3d;
|
||||
typedef Frustum3<float> Frustum3f;
|
||||
typedef Frustum3<Real> Frustum3r;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
228
tjp/core/math/Math.hpp
Executable file
228
tjp/core/math/Math.hpp
Executable file
@@ -0,0 +1,228 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Vector3.hpp"
|
||||
#include "Vector2.hpp"
|
||||
#include <cstddef>
|
||||
#include <array>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
struct Ray3
|
||||
{
|
||||
Vector3<Real> origin, direction;
|
||||
} ;
|
||||
|
||||
template<typename Real>
|
||||
struct Line3
|
||||
{
|
||||
Vector3<Real> origin, direction;
|
||||
} ;
|
||||
|
||||
template<typename Real>
|
||||
class Plane3
|
||||
{
|
||||
public:
|
||||
typedef Real value_type;
|
||||
|
||||
Vector3<Real> normal;
|
||||
Real constant;
|
||||
|
||||
Plane3 () {}
|
||||
|
||||
Plane3 (const Vector3<Real> &normal_, Real constant_) :
|
||||
normal(normal_),
|
||||
constant(constant_)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Plane3 (const Vector3<Real> &o, const Vector3<Real> &d)
|
||||
{
|
||||
normal = d;
|
||||
constant = d * o;
|
||||
}
|
||||
|
||||
Plane3 (const Vector3<Real> &p0, const Vector3<Real> &p1, const Vector3<Real> &p2)
|
||||
{
|
||||
auto v1 = p2 - p0;
|
||||
auto v2 = p1 - p0;
|
||||
normal = (v1 ^ v2).normalize();
|
||||
constant = normal * p0;
|
||||
}
|
||||
|
||||
int whichSide(const Vector3<Real> &p) const;
|
||||
Real distanceTo (const Vector3<Real> &p) const;
|
||||
|
||||
Vector3<Real> closestPoint(const Vector3<Real> &v) const;
|
||||
|
||||
};
|
||||
|
||||
template<typename Real>
|
||||
class Frustum3
|
||||
{
|
||||
public:
|
||||
typedef Real value_type;
|
||||
|
||||
Vector3<Real> origin, dVector, uVector, rVector;
|
||||
Real dMin, dMax, uBound, rBound;
|
||||
|
||||
template<typename U>
|
||||
Frustum3<U> asType() const
|
||||
{
|
||||
return Frustum3<U> {
|
||||
origin.template asType<U>(),
|
||||
dVector.template asType<U>(),
|
||||
uVector.template asType<U>(),
|
||||
rVector.template asType<U>(),
|
||||
(U)dMin, (U)dMax, (U)uBound, (U)rBound
|
||||
};
|
||||
}
|
||||
} ;
|
||||
|
||||
//template<typename Real>
|
||||
//struct Box3
|
||||
//{
|
||||
// typedef Real value_type;
|
||||
//
|
||||
// Vector3<Real> center;
|
||||
// std::array<Vector3<Real>, 3> axis;
|
||||
// Vector3<Real> extent;
|
||||
//} ;
|
||||
|
||||
template<typename Real>
|
||||
struct Cone3
|
||||
{
|
||||
typedef Real value_type;
|
||||
|
||||
Ray3<Real> ray;
|
||||
Real angle;
|
||||
} ;
|
||||
|
||||
template<typename Real>
|
||||
struct Segment2
|
||||
{
|
||||
typedef Real value_type;
|
||||
|
||||
Vector2<Real> begin, end;
|
||||
} ;
|
||||
|
||||
template<typename Real>
|
||||
struct Segment3
|
||||
{
|
||||
typedef Real value_type;
|
||||
|
||||
Vector3<Real> begin, end;
|
||||
} ;
|
||||
|
||||
template<typename Real>
|
||||
class Circle2
|
||||
{
|
||||
public:
|
||||
typedef Real value_type;
|
||||
|
||||
Vector2<Real> center;
|
||||
Real radius;
|
||||
|
||||
Circle2 () {}
|
||||
|
||||
Circle2 (const Vector2<Real> ¢er_, Real radius_) :
|
||||
center(center_),
|
||||
radius(radius_)
|
||||
{
|
||||
}
|
||||
|
||||
const static Circle2 Zero;
|
||||
};
|
||||
|
||||
template<typename Real>
|
||||
class Circle3
|
||||
{
|
||||
public:
|
||||
typedef Real value_type;
|
||||
|
||||
Vector3<Real> center;
|
||||
Vector3<Real> normal;
|
||||
Real radius;
|
||||
|
||||
Circle3 () {}
|
||||
|
||||
Circle3 (const Vector3<Real> ¢er_, const Vector3<Real> &normal_, Real radius_) :
|
||||
center(center_),
|
||||
normal(normal_),
|
||||
radius(radius_)
|
||||
{
|
||||
}
|
||||
|
||||
const static Circle3 Zero;
|
||||
};
|
||||
|
||||
template<typename Real>
|
||||
const Circle3<Real> Circle3<Real>::Zero = {
|
||||
Vector3<Real>::Zero, Vector3<Real>::Zero, 0
|
||||
};
|
||||
|
||||
|
||||
template<typename Real>
|
||||
class Triangle3
|
||||
{
|
||||
public:
|
||||
Vector3<Real> v[3];
|
||||
|
||||
Vector3<Real> normal() const
|
||||
{
|
||||
auto s0 = v[0] - v[1];
|
||||
auto s1 = v[0] - v[2];
|
||||
|
||||
return cross(s0, s1);
|
||||
}
|
||||
} ;
|
||||
|
||||
typedef double Real;
|
||||
|
||||
const Real Meter = 1.0;
|
||||
const Real Centimeter = 0.01;
|
||||
const Real Millimeter = 0.001;
|
||||
|
||||
typedef Ray3<double> Ray3d;
|
||||
typedef Ray3<float> Ray3f;
|
||||
typedef Ray3<Real> Ray3r;
|
||||
|
||||
typedef Segment2<double> Segment2d;
|
||||
typedef Segment2<float> Segment2f;
|
||||
typedef Segment2<Real> Segment2r;
|
||||
|
||||
typedef Circle2<double> Circle2d;
|
||||
typedef Circle2<float> Circle2f;
|
||||
typedef Circle2<Real> Circle2r;
|
||||
|
||||
typedef Line3<double> Line3d;
|
||||
typedef Line3<float> Line3f;
|
||||
typedef Line3<Real> Line3r;
|
||||
|
||||
typedef Plane3<float> Plane3f;
|
||||
typedef Plane3<double> Plane3d;
|
||||
typedef Plane3<Real> Plane3r;
|
||||
|
||||
typedef Cone3<float> Cone3f;
|
||||
typedef Cone3<double> Cone3d;
|
||||
typedef Cone3<Real> Cone3r;
|
||||
|
||||
typedef Frustum3<double> Frustum3d;
|
||||
typedef Frustum3<float> Frustum3f;
|
||||
typedef Frustum3<Real> Frustum3r;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
100
tjp/core/math/Math.inl
Executable file
100
tjp/core/math/Math.inl
Executable file
@@ -0,0 +1,100 @@
|
||||
//
|
||||
// Math.inl
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Math.hpp"
|
||||
#include "Zero.h"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Real Plane3<Real>::distanceTo (const Vector3<Real>& p) const
|
||||
{
|
||||
return (normal * p) - constant;
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
int Plane3<Real>::whichSide (const Vector3<Real> & p) const
|
||||
{
|
||||
Real distance = distanceTo(p);
|
||||
|
||||
if (distance < 0.0f)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (distance > 0.0f)
|
||||
{
|
||||
return +1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Real angleBetween (const Vector3<Real> &l, const Vector3<Real> &r)
|
||||
{
|
||||
auto v1 = l.normalize();
|
||||
auto v2 = r.normalize();
|
||||
// | unit(V1) * unit(V2) | = cos A
|
||||
double cosA = v1 * v2;
|
||||
// if the shadow is completely in the same direction, then the
|
||||
// difference in angle is zero
|
||||
const double episolon = 0.00001;
|
||||
const auto oneMepsilon = 1 - episolon;
|
||||
const auto negOneMepsilon = -1 + episolon;
|
||||
|
||||
if (cosA >= oneMepsilon)
|
||||
return 0;
|
||||
// if the shadow is completely in the opposite direction, then the
|
||||
// difference in angle is PI
|
||||
if (cosA <= negOneMepsilon)
|
||||
return constants<Real>::PI;
|
||||
|
||||
double Acos = acos(cosA);
|
||||
return (Real) Acos;
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Vector3<Real> axisBetween (const Vector3<Real> &l, const Vector3<Real> &r)
|
||||
{
|
||||
return (l ^ r).normalize();
|
||||
}
|
||||
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Vector3<Real> Plane3<Real>::closestPoint (const Vector3<Real> &p) const
|
||||
{
|
||||
// http://stackoverflow.com/questions/9605556/how-to-project-a-3d-point-to-a-3d-plane
|
||||
|
||||
auto r = p - (normal * p + constant) * normal;
|
||||
return r;
|
||||
}
|
||||
|
||||
// --------
|
||||
|
||||
template<typename Real>
|
||||
Real area(const math::Triangle3<Real> &t)
|
||||
{
|
||||
auto e0 = t.v[1] - t.v[0];
|
||||
auto e1 = t.v[2] - t.v[0];
|
||||
return length(cross(e0, e1)) / 2;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
102
tjp/core/math/MathGlmC.h
Executable file
102
tjp/core/math/MathGlmC.h
Executable file
@@ -0,0 +1,102 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "HPoint.hpp"
|
||||
#include "HMatrix.hpp"
|
||||
#include "Vector3.hpp"
|
||||
#include "Vector4.hpp"
|
||||
|
||||
#include <tjp/core/graphics/glm.h>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename T>
|
||||
glm::vec<3, T> glm_c(const math::Vector3<T> &v)
|
||||
{
|
||||
return { v[0], v[1], v[2] };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
math::Vector3<T> glm_c(const glm::vec<3, T> &v)
|
||||
{
|
||||
return { v[0], v[1], v[2] };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
glm::qua<T> glm_c(const math::Vector4<T> &v)
|
||||
{
|
||||
return { v[0], v[1], v[2], v[3] };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
math::Vector4<T> glm_c(const glm::qua<T> &v)
|
||||
{
|
||||
return { v[0], v[1], v[2], v[3] };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
glm::vec<4, T> glm_c(const math::HPoint<T> &v)
|
||||
{
|
||||
return { v[0], v[1], v[2], v[3] };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
math::HPoint<T> glm_c(const glm::vec<4, T> &v)
|
||||
{
|
||||
return { v[0], v[1], v[2], v[3] };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
glm::mat<3, 3, T> glm_c(const math::Matrix3<T> &m)
|
||||
{
|
||||
return {
|
||||
m[0][0], m[0][1], m[0][2],
|
||||
m[1][0], m[1][1], m[1][2],
|
||||
m[2][0], m[2][1], m[2][2]
|
||||
} ;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
math::Matrix3<T> glm_c(const glm::mat<3, 3, T> &m)
|
||||
{
|
||||
return {
|
||||
m[0][0], m[0][1], m[0][2],
|
||||
m[1][0], m[1][1], m[1][2],
|
||||
m[2][0], m[2][1], m[2][2]
|
||||
} ;
|
||||
}
|
||||
template<typename T>
|
||||
glm::mat<4, 4, T> glm_c(const math::HMatrix<T> &m)
|
||||
{
|
||||
return {
|
||||
m[0][0], m[0][1], m[0][2], m[0][3],
|
||||
m[1][0], m[1][1], m[1][2], m[1][3],
|
||||
m[2][0], m[2][1], m[2][2], m[2][3],
|
||||
m[3][0], m[3][1], m[3][2], m[3][3]
|
||||
} ;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
math::HMatrix<T> glm_c(const glm::mat<4, 4, T> &m)
|
||||
{
|
||||
return {
|
||||
m[0][0], m[0][1], m[0][2], m[0][3],
|
||||
m[1][0], m[1][1], m[1][2], m[1][3],
|
||||
m[2][0], m[2][1], m[2][2], m[2][3],
|
||||
m[3][0], m[3][1], m[3][2], m[3][3]
|
||||
} ;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
32
tjp/core/math/Matrix3.cpp
Executable file
32
tjp/core/math/Matrix3.cpp
Executable file
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// Math.cpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#include "Matrix3.hpp"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
|
||||
template<>
|
||||
const Matrix3<double> Matrix3<double>::Zero {
|
||||
0, 0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, 0
|
||||
};
|
||||
|
||||
template<>
|
||||
const Matrix3<double> Matrix3<double>::Identity {
|
||||
1, 0, 0,
|
||||
0, 1, 0,
|
||||
0, 0, 1
|
||||
};
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
25
tjp/core/math/Matrix3.h
Executable file
25
tjp/core/math/Matrix3.h
Executable file
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
class Matrix3;
|
||||
|
||||
typedef Matrix3<Real> Matrix3r;
|
||||
typedef Matrix3<float> Matrix3f;
|
||||
typedef Matrix3<double> Matrix3d;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
70
tjp/core/math/Matrix3.hpp
Executable file
70
tjp/core/math/Matrix3.hpp
Executable file
@@ -0,0 +1,70 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Vector3.hpp"
|
||||
#include <initializer_list>
|
||||
#include <array>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
class Matrix3
|
||||
{
|
||||
public:
|
||||
typedef Real value_type;
|
||||
|
||||
Real v[9];
|
||||
|
||||
public:
|
||||
Matrix3<Real>(std::initializer_list<Real> l)
|
||||
{
|
||||
int i=0;
|
||||
for (auto &r: l)
|
||||
v[i++] = r;
|
||||
}
|
||||
|
||||
Matrix3<Real> (const Vector3<Real> &a, const Vector3<Real> &b);
|
||||
Matrix3<Real> (const Vector3<Real> &a, const Vector3<Real> &b, const Vector3<Real> &c);
|
||||
Matrix3<Real> () {}
|
||||
|
||||
const Real* operator[] (size_t row) const;
|
||||
Real* operator[] (size_t row);
|
||||
|
||||
Matrix3<Real> transpose() const;
|
||||
Matrix3<Real> inverse(Real epsilon) const;
|
||||
|
||||
static const Matrix3<Real> Zero;
|
||||
static const Matrix3<Real> Identity;
|
||||
} ;
|
||||
|
||||
template<typename Real>
|
||||
const Matrix3<Real> Matrix3<Real>::Zero = {
|
||||
0, 0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, 0
|
||||
};
|
||||
|
||||
template<typename Real>
|
||||
const Matrix3<Real> Matrix3<Real>::Identity = {
|
||||
1, 0, 0,
|
||||
0, 1, 0,
|
||||
0, 0, 1
|
||||
};
|
||||
|
||||
typedef Matrix3<Real> Matrix3r;
|
||||
typedef Matrix3<float> Matrix3f;
|
||||
typedef Matrix3<double> Matrix3d;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
200
tjp/core/math/Matrix3.inl
Executable file
200
tjp/core/math/Matrix3.inl
Executable file
@@ -0,0 +1,200 @@
|
||||
//
|
||||
// Math.inl
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "Matrix3.hpp"
|
||||
#include "HPoint.hpp"
|
||||
#include "Zero.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
|
||||
#include "HMatrix.inl"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
//// inline
|
||||
//template<typename Real>
|
||||
//Matrix3<Real>::Matrix3(std::initializer_list<Real> l)
|
||||
//{
|
||||
// int i=0;
|
||||
// for (auto &r : l)
|
||||
// v[i++] = r;
|
||||
//}
|
||||
|
||||
/*
|
||||
// inline
|
||||
template<typename Real>
|
||||
Matrix3<Real>::Matrix3<Real> (const Vector3<Real> &a, const Vector3<Real> &b)
|
||||
{
|
||||
// http://gamedev.stackexchange.com/questions/20097/how-to-calculate-a-3x3-rotation-matrix-from-2-direction-vectors
|
||||
|
||||
auto x = a.normalize();
|
||||
auto y = b.normalize();
|
||||
|
||||
Matrix3<Real> &m = *this;
|
||||
|
||||
Vector3<Real> *mx = (Vector3<Real> *)m[0];
|
||||
Vector3<Real> *my = (Vector3<Real> *)m[1];
|
||||
Vector3<Real> *mz = (Vector3<Real> *)m[2];
|
||||
|
||||
*mx = x;
|
||||
*mz = (x^y).normalize();
|
||||
*my = (*mz ^ x).normalize();
|
||||
}
|
||||
*/
|
||||
|
||||
template<typename Real>
|
||||
Matrix3<Real>::Matrix3 (const Vector3<Real> &a, const Vector3<Real> &b, const Vector3<Real> &c)
|
||||
{
|
||||
v[0] = a[0];
|
||||
v[1] = a[1];
|
||||
v[2] = a[2];
|
||||
v[3] = b[0];
|
||||
v[4] = b[1];
|
||||
v[5] = b[2];
|
||||
v[6] = c[0];
|
||||
v[7] = c[1];
|
||||
v[8] = c[2];
|
||||
}
|
||||
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Matrix3<Real>::Matrix3 (const Vector3<Real> &a, const Vector3<Real> &b)
|
||||
{
|
||||
// http://math.stackexchange.com/questions/180418/calculate-rotation-matrix-to-align-vector-a-to-vector-b-in-3d
|
||||
|
||||
auto acb = a ^ b;
|
||||
auto s = acb.length();
|
||||
auto c = a * b;
|
||||
|
||||
Real vn[] {
|
||||
c, -s, 0,
|
||||
s, c, 0,
|
||||
0, 0, 1
|
||||
};
|
||||
|
||||
for (int i=0; i<9; ++i)
|
||||
v[i] = vn[i];
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Matrix3<Real> rotationMatrix(const Vector3<Real> &axis, const Real &angle)
|
||||
{
|
||||
Real cosTheta = std::cos(angle);
|
||||
Real sinTheta = std::sin(angle);
|
||||
Real oneMinusCosTheta = 1 - cosTheta;
|
||||
|
||||
Real x = axis[0];
|
||||
Real y = axis[1];
|
||||
Real z = axis[2];
|
||||
|
||||
Matrix3<Real> result;
|
||||
result[0][0] = cosTheta + x * x * oneMinusCosTheta;
|
||||
result[0][1] = x * y * oneMinusCosTheta - z * sinTheta;
|
||||
result[0][2] = x * z * oneMinusCosTheta + y * sinTheta;
|
||||
|
||||
result[1][0] = y * x * oneMinusCosTheta + z * sinTheta;
|
||||
result[1][1] = cosTheta + y * y * oneMinusCosTheta;
|
||||
result[1][2] = y * z * oneMinusCosTheta - x * sinTheta;
|
||||
|
||||
result[2][0] = z * x * oneMinusCosTheta - y * sinTheta;
|
||||
result[2][1] = z * y * oneMinusCosTheta + x * sinTheta;
|
||||
result[2][2] = cosTheta + z * z * oneMinusCosTheta;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Matrix3<Real> Matrix3<Real>::transpose() const
|
||||
{
|
||||
return Matrix3<Real>({
|
||||
v[0],
|
||||
v[3],
|
||||
v[6],
|
||||
v[1],
|
||||
v[4],
|
||||
v[7],
|
||||
v[2],
|
||||
v[5],
|
||||
v[8]
|
||||
});
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Matrix3<Real> Matrix3<Real>::inverse(const Real epsilon) const
|
||||
{
|
||||
// Invert a 3x3 using cofactors. This is faster than using a generic
|
||||
// Gaussian elimination because of the loop overhead of such a method.
|
||||
|
||||
Matrix3 inverse;
|
||||
|
||||
// Compute the adjoint.
|
||||
inverse.v[0] = v[4]*v[8] - v[5]*v[7];
|
||||
inverse.v[1] = v[2]*v[7] - v[1]*v[8];
|
||||
inverse.v[2] = v[1]*v[5] - v[2]*v[4];
|
||||
inverse.v[3] = v[5]*v[6] - v[3]*v[8];
|
||||
inverse.v[4] = v[0]*v[8] - v[2]*v[6];
|
||||
inverse.v[5] = v[2]*v[3] - v[0]*v[5];
|
||||
inverse.v[6] = v[3]*v[7] - v[4]*v[6];
|
||||
inverse.v[7] = v[1]*v[6] - v[0]*v[7];
|
||||
inverse.v[8] = v[0]*v[4] - v[1]*v[3];
|
||||
|
||||
Real det = v[0]*inverse.v[0] + v[1]*inverse.v[3] +
|
||||
v[2]*inverse.v[6];
|
||||
|
||||
if (std::abs(det) > epsilon)
|
||||
{
|
||||
Real invDet = ((Real)1)/det;
|
||||
inverse.v[0] *= invDet;
|
||||
inverse.v[1] *= invDet;
|
||||
inverse.v[2] *= invDet;
|
||||
inverse.v[3] *= invDet;
|
||||
inverse.v[4] *= invDet;
|
||||
inverse.v[5] *= invDet;
|
||||
inverse.v[6] *= invDet;
|
||||
inverse.v[7] *= invDet;
|
||||
inverse.v[8] *= invDet;
|
||||
return inverse;
|
||||
}
|
||||
|
||||
return Zero;
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Vector3<Real> operator *(const Matrix3<Real> &m, const Vector3<Real> &p)
|
||||
{
|
||||
HMatrix<Real> hm(m, Vector3<Real>::Zero, { 1, 1, 1 });
|
||||
HPoint<Real> hp(p);
|
||||
auto v = hm * hp;
|
||||
return { v.v[0], v.v[1], v.v[2] };
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
const Real* Matrix3<Real>::operator[] (size_t row) const
|
||||
{
|
||||
return &v[3*row];
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Real* Matrix3<Real>::operator[] (size_t row)
|
||||
{
|
||||
return &v[3*row];
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
44
tjp/core/math/Precision.h
Normal file
44
tjp/core/math/Precision.h
Normal file
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// MathIO.h
|
||||
// common
|
||||
//
|
||||
// Created by Timothy Prepscius on 8/4/18.
|
||||
// Copyright © 2018 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Real.h"
|
||||
|
||||
#include "Accuracy+IO.h"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename V, Real M>
|
||||
struct Precision
|
||||
{
|
||||
V v;
|
||||
|
||||
operator V&()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator const V&() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
} ;
|
||||
|
||||
template<typename IO, typename T, Real M>
|
||||
void io_ (IO &io, Precision<T, M> &v)
|
||||
{
|
||||
io.any(with_accuracy(v, M));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
86
tjp/core/math/Real.cpp
Executable file
86
tjp/core/math/Real.cpp
Executable file
@@ -0,0 +1,86 @@
|
||||
//
|
||||
// Math.cpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#include "Math.hpp"
|
||||
#include "Real.hpp"
|
||||
#include "Real.inl"
|
||||
#include <cmath>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
// http://www.codecodex.com/wiki/Calculate_an_integer_square_root
|
||||
template<typename T>
|
||||
T IntSqrt(T v)
|
||||
{
|
||||
T remainder = v;
|
||||
if (remainder < 0) { return 0; }
|
||||
|
||||
T one = 1;
|
||||
T place = one <<(sizeof(T)*8 -2);
|
||||
|
||||
while (place > remainder) { place /= 4; }
|
||||
|
||||
T root = 0;
|
||||
while (place)
|
||||
{
|
||||
if (remainder >= root + place)
|
||||
{
|
||||
remainder -= root + place;
|
||||
root += place*2;
|
||||
}
|
||||
root /= 2;
|
||||
place /= 4;
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
// float
|
||||
|
||||
template<>
|
||||
u128 sqrt(const u128 &v)
|
||||
{
|
||||
return IntSqrt<u128>(v);
|
||||
}
|
||||
|
||||
template<>
|
||||
s128 sqrt(const s128 &v)
|
||||
{
|
||||
return IntSqrt<s128>(v);
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
const double tjp::core::math::constants<double>::PI = atan<double>(1)*4.0;
|
||||
|
||||
template<>
|
||||
const float tjp::core::math::constants<float>::PI = atan<float>(1)*4.0;
|
||||
|
||||
template<>
|
||||
const double tjp::core::math::constants<double>::TWO_PI = atan<double>(1)*8.0;
|
||||
|
||||
template<>
|
||||
const float tjp::core::math::constants<float>::TWO_PI = atan<float>(1)*8.0;
|
||||
|
||||
template<>
|
||||
const float tjp::core::math::constants<float>::DEGREES_TO_RADIANS = 4.0 / 180.0 * atan<float>(1);
|
||||
|
||||
template<>
|
||||
const float tjp::core::math::constants<float>::RADIANS_TO_DEGREES = 180.0 / 4.0 / atan<float>(1);
|
||||
|
||||
template<>
|
||||
const double tjp::core::math::constants<double>::DEGREES_TO_RADIANS = 4.0 / 180.0 * atan<double>(1);
|
||||
|
||||
template<>
|
||||
const double tjp::core::math::constants<double>::RADIANS_TO_DEGREES = 180.0 / 4.0 / atan<double>(1);
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
83
tjp/core/math/Real.h
Executable file
83
tjp/core/math/Real.h
Executable file
@@ -0,0 +1,83 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tjp/core/types/Types.h>
|
||||
#include <tjp/core/types/Types+IO.h>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
typedef r64 Real;
|
||||
|
||||
template<typename Real>
|
||||
Real abs(const Real &);
|
||||
|
||||
template<typename Real>
|
||||
Real sqrt(const Real &);
|
||||
|
||||
template<typename Real>
|
||||
Real sin(const Real &);
|
||||
|
||||
template<typename Real>
|
||||
Real cos(const Real &);
|
||||
|
||||
template<typename Real>
|
||||
Real ceil(const Real &);
|
||||
|
||||
template<typename Real>
|
||||
Real floor(const Real &);
|
||||
|
||||
template<typename Real>
|
||||
Real acos(const Real &);
|
||||
|
||||
template<typename Real>
|
||||
Real atan(const Real &);
|
||||
|
||||
template<typename Real>
|
||||
Real atan2(const Real &, const Real &);
|
||||
|
||||
template<typename Real>
|
||||
Real hypot(const Real &, const Real &);
|
||||
|
||||
template<typename Real>
|
||||
Real pow2(const Real &);
|
||||
|
||||
template<typename Real>
|
||||
Real length(const Real &);
|
||||
|
||||
template<typename Real>
|
||||
Real min_value(const Real &lhs, const Real &rhs);
|
||||
|
||||
template<typename Real>
|
||||
Real max_value(const Real &lhs, const Real &rhs);
|
||||
|
||||
template<typename T>
|
||||
math::Real toReal (const T &v)
|
||||
{
|
||||
return (math::Real)v;
|
||||
}
|
||||
|
||||
template<>
|
||||
u128 abs(const u128 &v);
|
||||
|
||||
template<>
|
||||
s128 abs(const s128 &v);
|
||||
|
||||
template<>
|
||||
u128 sqrt(const u128 &v);
|
||||
|
||||
template<>
|
||||
s128 sqrt(const s128 &v);
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
43
tjp/core/math/Real.hpp
Executable file
43
tjp/core/math/Real.hpp
Executable file
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Real.h"
|
||||
#include "Zero.h"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
struct constants {
|
||||
static const Real PI;
|
||||
static const Real TWO_PI;
|
||||
|
||||
static const Real DEGREES_TO_RADIANS;
|
||||
static const Real RADIANS_TO_DEGREES;
|
||||
} ;
|
||||
|
||||
template<>
|
||||
const double tjp::core::math::constants<double>::PI;
|
||||
|
||||
template<>
|
||||
const float tjp::core::math::constants<float>::PI;
|
||||
|
||||
template<>
|
||||
const double tjp::core::math::constants<double>::TWO_PI;
|
||||
|
||||
template<>
|
||||
const float tjp::core::math::constants<float>::TWO_PI;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
#include "Real.inl"
|
||||
174
tjp/core/math/Real.inl
Executable file
174
tjp/core/math/Real.inl
Executable file
@@ -0,0 +1,174 @@
|
||||
//
|
||||
// Math.inl
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
// inline
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Real.hpp"
|
||||
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename T>
|
||||
T clamp(const T &t, T l=0, T r=1)
|
||||
{
|
||||
return std::min(std::max(t, l), r);
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Real ceil(const Real &r)
|
||||
{
|
||||
return std::ceil(r);
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Real floor(const Real &r)
|
||||
{
|
||||
return std::floor(r);
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Real trunc(const Real &r)
|
||||
{
|
||||
return std::trunc(r);
|
||||
}
|
||||
|
||||
|
||||
template<typename Real>
|
||||
Real pow2(const Real &r)
|
||||
{
|
||||
return r*r;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Real min_value(const Real &lhs, const Real &rhs)
|
||||
{
|
||||
if (lhs < rhs)
|
||||
return lhs;
|
||||
|
||||
return rhs;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Real max_value(const Real &lhs, const Real &rhs)
|
||||
{
|
||||
if (lhs > rhs)
|
||||
return lhs;
|
||||
|
||||
return rhs;
|
||||
}
|
||||
|
||||
|
||||
template<typename Real>
|
||||
Real sign_of(const Real & a)
|
||||
{
|
||||
if (a < 0)
|
||||
return (Real)-1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Real abs(const Real & a)
|
||||
{
|
||||
return std::abs(a);
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Real sin(const Real & a)
|
||||
{
|
||||
return std::sin(a);
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Real cos(const Real & a)
|
||||
{
|
||||
return std::cos(a);
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Real sqrt(const Real &v)
|
||||
{
|
||||
return std::sqrt(v);
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Real acos(const Real & v)
|
||||
{
|
||||
return std::acos(v);
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Real atan(const Real & v)
|
||||
{
|
||||
return std::atan(v);
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Real atan2(const Real & v, const Real & e)
|
||||
{
|
||||
return std::atan2(v, e);
|
||||
}
|
||||
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Real hypot(const Real & v, const Real & e)
|
||||
{
|
||||
return std::hypot(v, e);
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Real length(const Real & r)
|
||||
{
|
||||
return abs(r);
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Real lengthSquared(Real r)
|
||||
{
|
||||
return r*r;
|
||||
}
|
||||
|
||||
// ----
|
||||
|
||||
template<>
|
||||
inline
|
||||
u128 abs(const u128 &v)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline
|
||||
s128 abs(const s128 &v)
|
||||
{
|
||||
return v >= 0 ? v : -v;
|
||||
}
|
||||
|
||||
|
||||
template<typename Real>
|
||||
Real fract(Real r)
|
||||
{
|
||||
Real _;
|
||||
return std::modf(r, &_);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
68
tjp/core/math/RelativeFront+IO.h
Normal file
68
tjp/core/math/RelativeFront+IO.h
Normal file
@@ -0,0 +1,68 @@
|
||||
//
|
||||
// MathIO.h
|
||||
// common
|
||||
//
|
||||
// Created by Timothy Prepscius on 8/4/18.
|
||||
// Copyright © 2018 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RelativeFront.h"
|
||||
#include "Accuracy+IO.h"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename IO, typename V>
|
||||
void io_r(IO &io, RelativeFront<V> &a)
|
||||
{
|
||||
auto &v = *a.v;
|
||||
io.on_vector_begin(v);
|
||||
|
||||
if (!v.empty())
|
||||
{
|
||||
io.on_vector_value(v.front());
|
||||
|
||||
auto &front = v.front();
|
||||
|
||||
typedef typename V::value_type VV;
|
||||
VV vv;
|
||||
Accuracy<VV> avv { &vv, a.m };
|
||||
|
||||
for (auto i=++v.begin(); i!=v.end(); ++i)
|
||||
{
|
||||
io.on_vector_value(avv);
|
||||
*i = vv + front;
|
||||
}
|
||||
}
|
||||
|
||||
io.on_vector_end(v);
|
||||
}
|
||||
|
||||
template<typename IO, typename V>
|
||||
void io_w(IO &io, const RelativeFront<V> &a)
|
||||
{
|
||||
auto &v = *a.v;
|
||||
io.on_vector_begin(v);
|
||||
|
||||
if (!v.empty())
|
||||
{
|
||||
auto &front = v.front();
|
||||
io.on_vector_value(front);
|
||||
|
||||
for (auto i=++v.begin(); i!=v.end(); ++i)
|
||||
{
|
||||
auto vv = *i - front;
|
||||
io.on_vector_value(with_accuracy(vv, a.m));
|
||||
}
|
||||
}
|
||||
|
||||
io.on_vector_end(v);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
31
tjp/core/math/RelativeFront.h
Normal file
31
tjp/core/math/RelativeFront.h
Normal file
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// MathIO.h
|
||||
// common
|
||||
//
|
||||
// Created by Timothy Prepscius on 8/4/18.
|
||||
// Copyright © 2018 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename V>
|
||||
struct RelativeFront
|
||||
{
|
||||
V *v;
|
||||
Real m;
|
||||
} ;
|
||||
|
||||
template<typename V>
|
||||
auto relative_front(V &v, Real m)
|
||||
{
|
||||
return RelativeFront<V> { &v, m };
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
23
tjp/core/math/Segment1.h
Executable file
23
tjp/core/math/Segment1.h
Executable file
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Real.h"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
struct Segment1;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
40
tjp/core/math/Segment1.hpp
Executable file
40
tjp/core/math/Segment1.hpp
Executable file
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Segment1.h"
|
||||
|
||||
#include "Vector3.hpp"
|
||||
#include "Vector2.hpp"
|
||||
#include <cstddef>
|
||||
#include <array>
|
||||
|
||||
#include "Zero.h"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
struct Segment1
|
||||
{
|
||||
typedef Real value_type;
|
||||
|
||||
Real begin, end;
|
||||
|
||||
static const Segment1 Zero;
|
||||
} ;
|
||||
|
||||
template<typename Real>
|
||||
const Segment1<Real> Segment1<Real>::Zero = { zero<Real>(), zero<Real>() };
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
90
tjp/core/math/Segment1.inl
Executable file
90
tjp/core/math/Segment1.inl
Executable file
@@ -0,0 +1,90 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Segment1.hpp"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
auto length(const Segment1<Real> &r)
|
||||
{
|
||||
return distance(r.end,r.begin);
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
auto length_squared(const Segment1<Real> &r)
|
||||
{
|
||||
return distance_squared(r.end,r.begin);
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
bool operator==(const Segment1<Real> &lhs, const Segment1<Real> &rhs)
|
||||
{
|
||||
return lhs.begin == rhs.begin && lhs.end == rhs.end;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Segment1<Real> operator +(const Segment1<Real> &lhs, const Segment1<Real> &rhs)
|
||||
{
|
||||
return {
|
||||
lhs.begin + rhs.begin,
|
||||
lhs.end + rhs.end
|
||||
};
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Segment1<Real> operator -(const Segment1<Real> &lhs, const Segment1<Real> &rhs)
|
||||
{
|
||||
return {
|
||||
lhs.begin - rhs.begin,
|
||||
lhs.end - rhs.end
|
||||
};
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Segment1<Real> operator /(const Segment1<Real> &lhs, const size_t &rhs)
|
||||
{
|
||||
return {
|
||||
(Real)(lhs.begin / rhs),
|
||||
(Real)(lhs.end / rhs)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
template<typename Real>
|
||||
auto distance(const Segment1<Real> &s0, const Segment1<Real> &s1)
|
||||
{
|
||||
return distance((s0.begin+s0.end),(s1.begin+s1.end)) - (length(s0) + length(s1));
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
auto distance_squared(const Segment1<Real> &s0, const Segment1<Real> &s1)
|
||||
{
|
||||
return distance_squared((s0.begin+s0.end),(s1.begin+s1.end)) - (length_squared(s0) + length_squared(s1));
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
auto distance_relative(const Segment1<Real> &s0, const Segment1<Real> &s1)
|
||||
{
|
||||
return distance(s0, s1);
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
void zero(Segment1<R> &v)
|
||||
{
|
||||
v = Segment1<R>::Zero;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
62
tjp/core/math/SimpleLine.cpp
Executable file
62
tjp/core/math/SimpleLine.cpp
Executable file
@@ -0,0 +1,62 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#include "SimpleLine.hpp"
|
||||
|
||||
#include "Vector2.inl"
|
||||
#include <tjp/core/assert/debug_assert.h>
|
||||
|
||||
namespace tjp::core::math {
|
||||
|
||||
SimpleLineCompute::SimpleLineCompute(std::initializer_list<math::Vector2f> l, bool cap_) :
|
||||
cap(cap_)
|
||||
{
|
||||
p.insert(p.end(), l.begin(), l.end());
|
||||
s.resize(p.size()-1);
|
||||
|
||||
if (p.empty())
|
||||
return ;
|
||||
|
||||
auto next = p.begin();
|
||||
auto prev = next++;
|
||||
auto write = s.begin();
|
||||
for ( ;next!=p.end(); prev = next++)
|
||||
{
|
||||
auto d = *next - *prev;
|
||||
debug_assert(d[0] != 0);
|
||||
|
||||
auto sv = d[1]/d[0];
|
||||
*write++ = sv;
|
||||
}
|
||||
}
|
||||
|
||||
float SimpleLineCompute::operator ()(float x)
|
||||
{
|
||||
debug_assert(!p.empty());
|
||||
|
||||
if (cap && x < p.front().x())
|
||||
return p.front().y();
|
||||
|
||||
auto last = p.size()-1;
|
||||
for (auto i=1; ; ++i)
|
||||
{
|
||||
auto &r = p[i];
|
||||
if (x < r.x() || i == last)
|
||||
{
|
||||
if (i == last && cap)
|
||||
return p[i].y();
|
||||
|
||||
auto &l = p[i-1];
|
||||
auto &s_ = s[i-1];
|
||||
return l.y() + (x-l.x()) * s_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
20
tjp/core/math/SimpleLine.h
Executable file
20
tjp/core/math/SimpleLine.h
Executable file
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
struct SimpleLineCompute;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
34
tjp/core/math/SimpleLine.hpp
Executable file
34
tjp/core/math/SimpleLine.hpp
Executable file
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#include "Vector2.hpp"
|
||||
#include <tjp/core/containers/Vector.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
struct SimpleLineCompute
|
||||
{
|
||||
core::Vector<math::Vector2f> p;
|
||||
core::Vector<float> s;
|
||||
bool cap;
|
||||
|
||||
SimpleLineCompute(
|
||||
std::initializer_list<math::Vector2f> l,
|
||||
bool cap
|
||||
);
|
||||
float operator ()(float x);
|
||||
} ;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
24
tjp/core/math/Sphere1.h
Executable file
24
tjp/core/math/Sphere1.h
Executable file
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename C,typename D=C>
|
||||
class Sphere1;
|
||||
|
||||
typedef Sphere1<s64> Sphere1i64;
|
||||
typedef Sphere1<s128> Sphere1i128;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
64
tjp/core/math/Sphere1.hpp
Executable file
64
tjp/core/math/Sphere1.hpp
Executable file
@@ -0,0 +1,64 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Sphere1.h"
|
||||
|
||||
#include "Zero.h"
|
||||
#include <tjp/core/types/Types.h>
|
||||
#include <limits>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename C, typename D>
|
||||
class Sphere1
|
||||
{
|
||||
public:
|
||||
typedef Real value_type;
|
||||
typedef D Distance;
|
||||
typedef C Center;
|
||||
|
||||
typedef Sphere1<C, D> Self;
|
||||
|
||||
Center center;
|
||||
Distance radius;
|
||||
|
||||
Sphere1 () {}
|
||||
Sphere1 (Center center_, Distance radius_) :
|
||||
center(center_),
|
||||
radius(radius_)
|
||||
{
|
||||
}
|
||||
|
||||
const static Self Zero;
|
||||
const static Self Infinite;
|
||||
|
||||
Distance distanceTo(Real p) const;
|
||||
Distance minDistanceTo (const Self &v) const;
|
||||
Distance maxDistanceTo (const Self &v) const;
|
||||
|
||||
Distance minDistanceTo (Real v) const;
|
||||
Distance maxDistanceTo (Real v) const;
|
||||
} ;
|
||||
|
||||
template<typename Center, typename Distance>
|
||||
const Sphere1<Center,Distance> Sphere1<Center,Distance>::Zero = { zero<Center>(), zero<Distance>() };
|
||||
|
||||
template<typename Center, typename Distance>
|
||||
const Sphere1<Center,Distance> Sphere1<Center,Distance>::Infinite = { zero<Center>(), std::numeric_limits<Distance>::infinity() };
|
||||
|
||||
typedef Sphere1<s64> Sphere1i64;
|
||||
typedef Sphere1<s128> Sphere1i128;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
117
tjp/core/math/Sphere1.inl
Executable file
117
tjp/core/math/Sphere1.inl
Executable file
@@ -0,0 +1,117 @@
|
||||
//
|
||||
// Math.inl
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Zero.h"
|
||||
#include "Sphere1.hpp"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename C, typename D>
|
||||
D Sphere1<C,D>::distanceTo (Real p) const
|
||||
{
|
||||
return (p - center) - radius;
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename C, typename D>
|
||||
D Sphere1<C,D>::minDistanceTo (const Self &p) const
|
||||
{
|
||||
return distance(p.center, center) - (radius + p.radius);
|
||||
}
|
||||
|
||||
template<typename C, typename D>
|
||||
D Sphere1<C,D>::maxDistanceTo (const Self & p) const
|
||||
{
|
||||
auto centerDistance = (p.center - center);
|
||||
auto diffRadius = std::abs(p.radius - radius);
|
||||
|
||||
// if the circle is within the other
|
||||
if (diffRadius > centerDistance)
|
||||
return diffRadius - centerDistance;
|
||||
|
||||
// if the circle is not within the other
|
||||
auto sumRadius = p.radius + radius;
|
||||
return centerDistance + sumRadius;
|
||||
}
|
||||
|
||||
template<typename C, typename D>
|
||||
bool operator ==(const Sphere1<C,D> &l, const Sphere1<C,D> &r)
|
||||
{
|
||||
return l.center == r.center && l.radius == r.radius;
|
||||
}
|
||||
|
||||
template<typename C, typename D>
|
||||
D distance (const Sphere1<C,D> &lhs, const Sphere1<C,D> &rhs)
|
||||
{
|
||||
return distance(lhs.center, rhs.center) - (lhs.radius + rhs.radius);
|
||||
}
|
||||
|
||||
template<typename C, typename D>
|
||||
D distance_squared (const Sphere1<C,D> &lhs, const Sphere1<C,D> &rhs)
|
||||
{
|
||||
return distance_squared(lhs.center, rhs.center) - pow2(lhs.radius + rhs.radius);
|
||||
}
|
||||
|
||||
template<typename C, typename D>
|
||||
D distance_relative(const Sphere1<C, D> &l, const Sphere1<C, D> &r)
|
||||
{
|
||||
return distance_squared(l, r);
|
||||
}
|
||||
|
||||
template<typename C, typename D>
|
||||
Sphere1<C, D> operator+(const Sphere1<C,D> &lhs, const Sphere1<C,D> &rhs)
|
||||
{
|
||||
return {
|
||||
lhs.center + rhs.center,
|
||||
lhs.radius + rhs.radius
|
||||
};
|
||||
}
|
||||
|
||||
template<typename C, typename D>
|
||||
Sphere1<C, D> operator-(const Sphere1<C,D> &lhs, const Sphere1<C,D> &rhs)
|
||||
{
|
||||
return {
|
||||
lhs.center - rhs.center,
|
||||
lhs.radius - rhs.radius
|
||||
};
|
||||
}
|
||||
|
||||
template<typename C, typename D>
|
||||
Sphere1<C, D> operator /(const Sphere1<C,D> &lhs, const D &rhs)
|
||||
{
|
||||
return {
|
||||
lhs.center / rhs,
|
||||
lhs.radius / rhs
|
||||
};
|
||||
}
|
||||
|
||||
template<typename C, typename D>
|
||||
Sphere1<C, D> operator /(const Sphere1<C,D> &lhs, size_t rhs)
|
||||
{
|
||||
return {
|
||||
lhs.center / rhs,
|
||||
lhs.radius / rhs
|
||||
};
|
||||
}
|
||||
|
||||
template<typename C, typename D>
|
||||
void zero(Sphere1<C, D> &v)
|
||||
{
|
||||
v = {
|
||||
zero<C>(),
|
||||
zero<D>()
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
43
tjp/core/math/Sphere3.cpp
Executable file
43
tjp/core/math/Sphere3.cpp
Executable file
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#include "Sphere3.hpp"
|
||||
#include "GTE_convert.hpp"
|
||||
|
||||
#define GTE_NO_LOGGER
|
||||
#include <Mathematics/MinimumVolumeSphere3.h>
|
||||
#include <Mathematics/ContSphere3.h>
|
||||
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
|
||||
Sphere3r minimumBoundingSphere(const Vector<math::Vector3r> &translates_)
|
||||
{
|
||||
if (translates_.empty())
|
||||
return Sphere3r::Zero;
|
||||
|
||||
std::vector<gte::Vector3<Real>> translates;
|
||||
|
||||
for (auto &p : translates_)
|
||||
translates.push_back(gte_c(p));
|
||||
|
||||
gte::Sphere3<Real> sphere;
|
||||
gte::MinimumVolumeSphere3<Real, Real> generator;
|
||||
generator(static_cast<int>(translates.size()), translates.data(), sphere);
|
||||
|
||||
return gte_c(sphere);
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
27
tjp/core/math/Sphere3.h
Executable file
27
tjp/core/math/Sphere3.h
Executable file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Real.h"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
class Sphere3;
|
||||
|
||||
typedef Sphere3<float> Sphere3f;
|
||||
typedef Sphere3<double> Sphere3d;
|
||||
typedef Sphere3<Real> Sphere3r;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
78
tjp/core/math/Sphere3.hpp
Executable file
78
tjp/core/math/Sphere3.hpp
Executable file
@@ -0,0 +1,78 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Sphere3.h"
|
||||
|
||||
#include "Zero.h"
|
||||
#include <tjp/core/types/Types.h>
|
||||
#include <limits>
|
||||
|
||||
#include "Vector3.hpp"
|
||||
#include <tjp/core/containers/Vector.hpp>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
class Sphere3
|
||||
{
|
||||
public:
|
||||
typedef Real value_type;
|
||||
|
||||
typedef Vector3<Real> Center;
|
||||
Center center;
|
||||
Real radius;
|
||||
|
||||
Sphere3 () {}
|
||||
|
||||
Sphere3 (const Vector3<Real> ¢er_, Real radius_) :
|
||||
center(center_),
|
||||
radius(radius_)
|
||||
{
|
||||
}
|
||||
|
||||
Real distanceTo(const Vector3<Real> &p) const;
|
||||
Real minDistanceTo (const Sphere3<Real> &v) const;
|
||||
Real maxDistanceTo (const Sphere3<Real> &v) const;
|
||||
|
||||
Real minDistanceTo (const Vector3<Real> &v) const;
|
||||
Real maxDistanceTo (const Vector3<Real> &v) const;
|
||||
|
||||
bool contains(const Vector3<Real> &p) const;
|
||||
bool contains(const Sphere3<Real> &v) const;
|
||||
|
||||
const static Sphere3 Zero;
|
||||
const static Sphere3 Infinite;
|
||||
|
||||
template<typename T>
|
||||
Sphere3<T> asType() const
|
||||
{
|
||||
return Sphere3<T> { center.template asType<T>(), T(radius) };
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Real>
|
||||
const Sphere3<Real> Sphere3<Real>::Zero = { Vector3<Real>::Zero, 0 };
|
||||
|
||||
template<typename Real>
|
||||
const Sphere3<Real> Sphere3<Real>::Infinite = { Vector3<Real>::Zero, std::numeric_limits<Real>::infinity() };
|
||||
|
||||
typedef Sphere3<float> Sphere3f;
|
||||
typedef Sphere3<double> Sphere3d;
|
||||
typedef Sphere3<Real> Sphere3r;
|
||||
|
||||
Sphere3r minimumBoundingSphere(const Vector<math::Vector3r> &points);
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
197
tjp/core/math/Sphere3.inl
Executable file
197
tjp/core/math/Sphere3.inl
Executable file
@@ -0,0 +1,197 @@
|
||||
//
|
||||
// Math.inl
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "Sphere3.hpp"
|
||||
#include "Real.hpp"
|
||||
#include "Vector3.inl"
|
||||
#include "Zero.h"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
bool operator==(const Sphere3<Real>& lhs, const Sphere3<Real>& rhs)
|
||||
{
|
||||
return lhs.center == rhs.center && lhs.radius == rhs.radius;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
bool operator!=(const Sphere3<Real>& lhs, const Sphere3<Real>& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Real Sphere3<Real>::distanceTo (const Vector3<Real>& p) const
|
||||
{
|
||||
return distance(p, center) - radius;
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Real Sphere3<Real>::minDistanceTo (const Sphere3<Real>& p) const
|
||||
{
|
||||
return distance(p.center, center) - (radius + p.radius);
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Real Sphere3<Real>::maxDistanceTo (const Sphere3<Real>& p) const
|
||||
{
|
||||
auto centerDistance = distance(p.center, center);
|
||||
auto diffRadius = std::abs(p.radius - radius);
|
||||
|
||||
// if the circle is within the other
|
||||
if (diffRadius > centerDistance)
|
||||
return diffRadius - centerDistance;
|
||||
|
||||
// if the circle is not within the other
|
||||
auto sumRadius = p.radius + radius;
|
||||
return centerDistance + sumRadius;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Real Sphere3<Real>::minDistanceTo (const Vector3<Real>& p) const
|
||||
{
|
||||
return (p - center).length() - radius;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Real Sphere3<Real>::maxDistanceTo (const Vector3<Real>& p) const
|
||||
{
|
||||
auto distance = (p - center).length();
|
||||
|
||||
if (radius > distance)
|
||||
return distance - radius;
|
||||
|
||||
return distance + radius;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Real distance(const Sphere3<Real> &l, const Sphere3<Real> &r)
|
||||
{
|
||||
return distance(l.center, r.center) - (l.radius + r.radius);
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Real distance(const Sphere3<Real> &l, const Vector3<Real> &r)
|
||||
{
|
||||
return distance(l.center, r) - (l.radius);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
template<typename Real>
|
||||
Real distance_squared_exact(const Sphere3<Real> &l, const Sphere3<Real> &r)
|
||||
{
|
||||
return pow2(distance(l, r));
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Real distance_squared_approx(const Sphere3<Real> &l, const Sphere3<Real> &r)
|
||||
{
|
||||
return distance_squared(l.center, r.center) - math::pow2(l.radius + r.radius);
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Real distance_squared(const Sphere3<Real> &l, const Vector3<Real> &r)
|
||||
{
|
||||
return distance_squared(l.center, r) - math::pow2(l.radius);
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Real distance_relative(const Sphere3<Real> &l, const Sphere3<Real> &r)
|
||||
{
|
||||
return distance_squared_approx(l, r);
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
bool Sphere3<Real>::contains (const Vector3<Real>& p) const
|
||||
{
|
||||
auto radiusSquared = radius * radius;
|
||||
return (p - center).lengthSquared() < radiusSquared;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
bool Sphere3<Real>::contains (const Sphere3<Real>& v) const
|
||||
{
|
||||
auto r = (radius - v.radius);
|
||||
auto r2 = r * r;
|
||||
return (v.center - center).lengthSquared() < r2;
|
||||
}
|
||||
|
||||
|
||||
template<typename Real>
|
||||
bool same(const Sphere3<Real> &lhs, const Sphere3<Real> &rhs, Real epsilon)
|
||||
{
|
||||
if ((lhs.center - rhs.center).length() > epsilon)
|
||||
return false;
|
||||
|
||||
if (std::abs(lhs.radius - rhs.radius) > epsilon)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
void zero(Sphere3<Real> &r)
|
||||
{
|
||||
r = {
|
||||
zero<typename Sphere3<Real>::Center>(),
|
||||
zero<Real>()
|
||||
} ;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Sphere3<Real> &operator +=(Sphere3<Real> &lhs, const Sphere3<Real> &rhs)
|
||||
{
|
||||
lhs.center += rhs.center;
|
||||
lhs.radius += rhs.radius;
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Sphere3<Real> operator +(const Sphere3<Real> &lhs, const Sphere3<Real> &rhs)
|
||||
{
|
||||
return { lhs.center+rhs.center, lhs.radius+rhs.radius };
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Sphere3<Real> operator -(const Sphere3<Real> &lhs, const Sphere3<Real> &rhs)
|
||||
{
|
||||
return { lhs.center-rhs.center, lhs.radius-rhs.radius };
|
||||
}
|
||||
|
||||
template<typename Real, typename U>
|
||||
Sphere3<Real> operator /(const Sphere3<Real> &lhs, const U &rhs)
|
||||
{
|
||||
return Sphere3<Real> {
|
||||
lhs.center / rhs,
|
||||
lhs.radius / rhs
|
||||
};
|
||||
}
|
||||
|
||||
template<typename Real, typename U>
|
||||
Sphere3<Real> operator *(const U &lhs, const Sphere3<Real> &rhs)
|
||||
{
|
||||
return Sphere3<Real> {
|
||||
lhs * rhs.center,
|
||||
lhs * rhs.radius
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
665
tjp/core/math/Statistics.h
Executable file
665
tjp/core/math/Statistics.h
Executable file
@@ -0,0 +1,665 @@
|
||||
//
|
||||
// Server.hpp
|
||||
// TimeSync
|
||||
//
|
||||
// Created by Timothy Prepscius on 1/27/17.
|
||||
// Copyright © 2017 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
#include <numeric>
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
#include <climits>
|
||||
#include <algorithm>
|
||||
#include <deque>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
struct RunningStatsWeightedAverager
|
||||
{
|
||||
typedef double T;
|
||||
double weight, oneMinusWeight;
|
||||
T m, s;
|
||||
bool initialized = false;
|
||||
|
||||
RunningStatsWeightedAverager(double weight_ = 0.8) :
|
||||
m(0),
|
||||
s(0),
|
||||
weight(weight_),
|
||||
oneMinusWeight(1.0 - weight_)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m = 0;
|
||||
s = 0;
|
||||
}
|
||||
|
||||
void initialize(T x)
|
||||
{
|
||||
m = x;
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
void push(T x)
|
||||
{
|
||||
if (!initialized)
|
||||
initialize(x);
|
||||
|
||||
// See Knuth TAOCP vol 2, 3rd edition, page 232
|
||||
auto newM = weight * m + oneMinusWeight * x;
|
||||
auto newS = weight * s + oneMinusWeight * std::abs(x - m);
|
||||
|
||||
// set up for next iteration
|
||||
m = newM;
|
||||
s = newS;
|
||||
}
|
||||
|
||||
double mean() const
|
||||
{
|
||||
return m;
|
||||
}
|
||||
|
||||
double error() const
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class RunningStats
|
||||
{
|
||||
public:
|
||||
RunningStats()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
n = 0;
|
||||
m = 0;
|
||||
s = 0;
|
||||
}
|
||||
|
||||
void push(T x)
|
||||
{
|
||||
n++;
|
||||
|
||||
// See Knuth TAOCP vol 2, 3rd edition, page 232
|
||||
auto newM = m + (x - m) / n;
|
||||
auto newS = s + (x - m)*(x - newM);
|
||||
|
||||
// set up for next iteration
|
||||
m = newM;
|
||||
s = newS;
|
||||
}
|
||||
|
||||
int numDataValues() const
|
||||
{
|
||||
return n;
|
||||
}
|
||||
|
||||
double mean() const
|
||||
{
|
||||
return (n > 0) ? m : 0.0;
|
||||
}
|
||||
|
||||
double variance() const
|
||||
{
|
||||
return ((n > 1) ? s / (n - 1) : 0.0);
|
||||
}
|
||||
|
||||
double standardDeviation() const
|
||||
{
|
||||
return std::sqrt(variance());
|
||||
}
|
||||
|
||||
private:
|
||||
int n;
|
||||
T m, s;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class AccumulatedStats
|
||||
{
|
||||
protected:
|
||||
std::vector<T> samples;
|
||||
|
||||
T unresolved;
|
||||
T m;
|
||||
T e;
|
||||
|
||||
void calculate()
|
||||
{
|
||||
m = e = unresolved;
|
||||
|
||||
if (samples.empty())
|
||||
return;
|
||||
|
||||
T s = 0;
|
||||
for (auto &t : samples)
|
||||
{
|
||||
s += t;
|
||||
}
|
||||
|
||||
m = s /= samples.size();
|
||||
|
||||
if (samples.size() < 2)
|
||||
return;
|
||||
|
||||
T s0 = 0;
|
||||
for (int i = 0; i < samples.size() / 2; ++i)
|
||||
{
|
||||
s0 += samples[i];
|
||||
}
|
||||
|
||||
T s1 = 0;
|
||||
for (int i = samples.size() / 2; i < samples.size(); ++i)
|
||||
{
|
||||
s1 += samples[i];
|
||||
}
|
||||
|
||||
s0 /= samples.size() / 2;
|
||||
s1 /= samples.size() - samples.size() / 2;
|
||||
|
||||
e = s1 - s0;
|
||||
}
|
||||
|
||||
public:
|
||||
AccumulatedStats(T unresolved)
|
||||
{
|
||||
this->unresolved = unresolved;
|
||||
}
|
||||
|
||||
void push(T t)
|
||||
{
|
||||
samples.push_back(t);
|
||||
calculate();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
samples.clear();
|
||||
calculate();
|
||||
}
|
||||
|
||||
T mean()
|
||||
{
|
||||
return m;
|
||||
}
|
||||
|
||||
T error()
|
||||
{
|
||||
return e;
|
||||
}
|
||||
|
||||
T errorSize()
|
||||
{
|
||||
return std::abs(e);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename R, typename T=R>
|
||||
R valueOf(const T &t) { return (R)t; }
|
||||
|
||||
template<typename R, typename T=R>
|
||||
R weightOf(const T &t) { return (R)1.0; }
|
||||
|
||||
template<typename T>
|
||||
double stdev_lengthSquared(const T &d)
|
||||
{
|
||||
return (double)d * (double)d;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T zero_of()
|
||||
{
|
||||
return (T)0.0;
|
||||
}
|
||||
|
||||
template<typename R, typename V>
|
||||
R mean(const V &v, std::function<R(const typename V::value_type &)> f=valueOf<R, typename V::value_type>)
|
||||
{
|
||||
R sum = zero_of<R>();
|
||||
for (auto &t : v)
|
||||
{
|
||||
sum += f(t);
|
||||
}
|
||||
|
||||
auto mean = sum / v.size();
|
||||
return mean;
|
||||
}
|
||||
|
||||
template<typename R, typename V>
|
||||
R weighted_mean(const V &v,
|
||||
std::function<R(const typename V::value_type &)> f=valueOf<R, typename V::value_type>,
|
||||
std::function<R(const typename V::value_type &)> w=weightOf<R, typename V::value_type>
|
||||
)
|
||||
{
|
||||
R sum = zero_of<R>();
|
||||
R weight = zero_of<R>();
|
||||
for (auto &t : v)
|
||||
{
|
||||
auto w_ = w(t);
|
||||
sum += w_ * f(t);
|
||||
weight += w_;
|
||||
}
|
||||
|
||||
auto mean = sum / weight;
|
||||
return mean;
|
||||
}
|
||||
|
||||
template<typename R, typename V>
|
||||
double stdev(const V &v, const R &mean, std::function<R(const typename V::value_type &)> f=valueOf<R, typename V::value_type>)
|
||||
{
|
||||
double sum = zero_of<double>();
|
||||
for (auto &t : v)
|
||||
{
|
||||
auto diff = f(t) - mean;
|
||||
sum += stdev_lengthSquared(diff);
|
||||
}
|
||||
|
||||
return std::sqrt(sum / (double)v.size());
|
||||
}
|
||||
|
||||
template<typename R, typename V>
|
||||
double stdev(const V &v, std::function<R(const typename V::value_type &)> f=valueOf<R, typename V::value_type>)
|
||||
{
|
||||
typedef typename V::value_type T;
|
||||
T mean = math::mean<T>(v, f);
|
||||
return stdev(v, mean);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct MeanStddev
|
||||
{
|
||||
T mean;
|
||||
T stddev;
|
||||
} ;
|
||||
|
||||
template<typename R, typename V>
|
||||
MeanStddev<R> rejectOutliersMeanStddev(const V &samples, R a, std::function<R(const typename V::value_type &)> f=valueOf<R, typename V::value_type>)
|
||||
{
|
||||
R m, e;
|
||||
|
||||
auto u = math::mean(samples);
|
||||
auto s = math::stdev(samples);
|
||||
|
||||
// filtered = [e for e in data_bad if (u - 2 * s < e < u + 2 * s)]
|
||||
std::vector<R> filtered;
|
||||
for (auto &v : samples)
|
||||
{
|
||||
if (u - a * s < v && v < u + a * s)
|
||||
{
|
||||
filtered.push_back(v);
|
||||
}
|
||||
}
|
||||
|
||||
if (filtered.empty())
|
||||
{
|
||||
m = e = 0;
|
||||
return { m, e };
|
||||
}
|
||||
|
||||
return { math::mean(filtered), math::stdev(filtered) };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class RejectOutlierStats
|
||||
{
|
||||
protected:
|
||||
std::vector<T> samples;
|
||||
|
||||
double a;
|
||||
T unresolved;
|
||||
T m;
|
||||
T e;
|
||||
|
||||
void calculate()
|
||||
{
|
||||
if (samples.empty())
|
||||
{
|
||||
m = e = unresolved;
|
||||
return;
|
||||
}
|
||||
|
||||
auto u = math::mean<T>(samples);
|
||||
auto s = math::stdev<T>(samples);
|
||||
|
||||
// filtered = [e for e in data_bad if (u - 2 * s < e < u + 2 * s)]
|
||||
std::vector<T> filtered;
|
||||
for (auto &v : samples)
|
||||
{
|
||||
if (u - a * s < v && v < u + a * s)
|
||||
{
|
||||
filtered.push_back(v);
|
||||
}
|
||||
}
|
||||
|
||||
if (filtered.empty())
|
||||
{
|
||||
m = e = unresolved;
|
||||
return;
|
||||
}
|
||||
|
||||
auto m = math::mean<T>(filtered);
|
||||
auto e = math::stdev<T>(filtered);
|
||||
|
||||
this->m = m;
|
||||
this->e = e;
|
||||
}
|
||||
|
||||
public:
|
||||
RejectOutlierStats(T unresolved, double a = 2.0)
|
||||
{
|
||||
this->unresolved = unresolved;
|
||||
m = e = unresolved;
|
||||
this->a = a;
|
||||
}
|
||||
|
||||
void push(T t)
|
||||
{
|
||||
samples.push_back(t);
|
||||
calculate();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
samples.clear();
|
||||
calculate();
|
||||
}
|
||||
|
||||
T mean()
|
||||
{
|
||||
return m;
|
||||
}
|
||||
|
||||
T error()
|
||||
{
|
||||
return e;
|
||||
}
|
||||
|
||||
T errorSize()
|
||||
{
|
||||
return std::abs(e);
|
||||
}
|
||||
|
||||
size_t size () const
|
||||
{
|
||||
return samples.size();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class WindowStats
|
||||
{
|
||||
protected:
|
||||
std::deque<T> samples;
|
||||
|
||||
int windowSize;
|
||||
double a;
|
||||
T unresolved;
|
||||
T m;
|
||||
T e;
|
||||
T l;
|
||||
|
||||
void calculate()
|
||||
{
|
||||
m = e = l = unresolved;
|
||||
|
||||
if (samples.empty())
|
||||
return;
|
||||
|
||||
auto &window = samples;
|
||||
|
||||
typedef double R;
|
||||
m = math::mean<R>(window);
|
||||
e = math::stdev<R>(window);
|
||||
}
|
||||
|
||||
public:
|
||||
WindowStats(T unresolved, int windowSize, double a = 2.0)
|
||||
{
|
||||
this->unresolved = unresolved;
|
||||
l = m = e = unresolved;
|
||||
this->a = a;
|
||||
this->windowSize = windowSize;
|
||||
}
|
||||
|
||||
void push(T t)
|
||||
{
|
||||
samples.push_front(t);
|
||||
while (samples.size() > windowSize)
|
||||
samples.pop_back();
|
||||
|
||||
calculate();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
samples.clear();
|
||||
calculate();
|
||||
}
|
||||
|
||||
T mean()
|
||||
{
|
||||
return m;
|
||||
}
|
||||
|
||||
T min()
|
||||
{
|
||||
return l;
|
||||
}
|
||||
|
||||
T error()
|
||||
{
|
||||
return e;
|
||||
}
|
||||
|
||||
T errorSize()
|
||||
{
|
||||
return std::abs(e);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class RejectOutlierWindowStats
|
||||
{
|
||||
protected:
|
||||
std::deque<T> samples;
|
||||
|
||||
int windowSize;
|
||||
double a;
|
||||
T unresolved;
|
||||
T m;
|
||||
T e;
|
||||
T l;
|
||||
|
||||
void calculate()
|
||||
{
|
||||
m = e = l = unresolved;
|
||||
|
||||
if (samples.empty())
|
||||
return;
|
||||
|
||||
auto &window = samples;
|
||||
|
||||
typedef double R;
|
||||
R u = math::mean<R>(window);
|
||||
R s = math::stdev<R>(window);
|
||||
|
||||
// filtered = [e for e in data_bad if (u - 2 * s < e < u + 2 * s)]
|
||||
std::vector<T> filtered;
|
||||
for (auto &v : window)
|
||||
{
|
||||
if (l == unresolved)
|
||||
l = v;
|
||||
else
|
||||
l = std::min(l, v);
|
||||
|
||||
if (u - a * s < v && v < u + a * s)
|
||||
{
|
||||
filtered.push_back(v);
|
||||
}
|
||||
}
|
||||
|
||||
if (filtered.empty())
|
||||
return;
|
||||
|
||||
m = math::mean<R>(filtered);
|
||||
|
||||
e = math::stdev<R>(filtered);
|
||||
}
|
||||
|
||||
public:
|
||||
RejectOutlierWindowStats(T unresolved, int windowSize, double a = 2.0)
|
||||
{
|
||||
this->unresolved = unresolved;
|
||||
l = m = e = unresolved;
|
||||
this->a = a;
|
||||
this->windowSize = windowSize;
|
||||
}
|
||||
|
||||
void push(T t)
|
||||
{
|
||||
samples.push_back(t);
|
||||
if (samples.size() > windowSize)
|
||||
samples.pop_front();
|
||||
|
||||
calculate();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
samples.clear();
|
||||
calculate();
|
||||
}
|
||||
|
||||
T mean()
|
||||
{
|
||||
return m;
|
||||
}
|
||||
|
||||
T min()
|
||||
{
|
||||
return l;
|
||||
}
|
||||
|
||||
T error()
|
||||
{
|
||||
return e;
|
||||
}
|
||||
|
||||
T errorSize()
|
||||
{
|
||||
return std::abs(e);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename T, typename R>
|
||||
class RejectOutlierUseBestStatsWindow
|
||||
{
|
||||
protected:
|
||||
typedef std::pair<T, R> Sample;
|
||||
std::vector<Sample> samples;
|
||||
int numSamplesToReduce;
|
||||
int numSamplesToInclude;
|
||||
|
||||
double a;
|
||||
T unresolved;
|
||||
T m;
|
||||
T e;
|
||||
|
||||
void calculate()
|
||||
{
|
||||
m = e = unresolved;
|
||||
|
||||
if (samples.empty())
|
||||
return;
|
||||
|
||||
auto numSamplesToReduce = std::min((int)samples.size(), this->numSamplesToReduce == -1 ? INT_MAX : this->numSamplesToReduce);
|
||||
std::vector<Sample> last(samples.end() - numSamplesToReduce, samples.end());
|
||||
|
||||
std::sort(last.begin(), last.end(), [](Sample &l, Sample &r) { return l.second < r.second; });
|
||||
auto numSamplesToInclude = std::min((int)last.size(), this->numSamplesToInclude);
|
||||
|
||||
std::vector<T> best;
|
||||
for (auto i = 0; i < numSamplesToInclude; ++i)
|
||||
{
|
||||
best.push_back(last[i].first);
|
||||
}
|
||||
|
||||
double u = math::mean(best);
|
||||
double s = math::stdev(best);
|
||||
|
||||
// filtered = [e for e in data_bad if (u - 2 * s < e < u + 2 * s)]
|
||||
std::vector<T> filtered;
|
||||
for (auto &v : best)
|
||||
{
|
||||
if (u - a * s < v && v < u + a * s)
|
||||
{
|
||||
filtered.push_back(v);
|
||||
}
|
||||
}
|
||||
|
||||
if (filtered.empty())
|
||||
return;
|
||||
|
||||
m = math::mean(filtered);
|
||||
e = math::stdev(filtered);
|
||||
}
|
||||
|
||||
public:
|
||||
RejectOutlierUseBestStatsWindow(T unresolved, int numSamplesToReduce, int numSamplesToInclude, double a = 2.0)
|
||||
{
|
||||
this->unresolved = unresolved;
|
||||
m = e = unresolved;
|
||||
this->a = a;
|
||||
|
||||
this->numSamplesToReduce = numSamplesToReduce;
|
||||
this->numSamplesToInclude = numSamplesToInclude;
|
||||
}
|
||||
|
||||
void push(T t, R r)
|
||||
{
|
||||
samples.push_back({ t, r });
|
||||
calculate();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
samples.clear();
|
||||
calculate();
|
||||
}
|
||||
|
||||
T mean()
|
||||
{
|
||||
return m;
|
||||
}
|
||||
|
||||
T error()
|
||||
{
|
||||
return e;
|
||||
}
|
||||
|
||||
T errorSize()
|
||||
{
|
||||
return std::abs(e);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
36
tjp/core/math/Vector2.h
Executable file
36
tjp/core/math/Vector2.h
Executable file
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Real.h"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename T>
|
||||
struct Vector2_;
|
||||
|
||||
typedef Vector2_<double> Vector2d_;
|
||||
typedef Vector2_<float> Vector2f_;
|
||||
typedef Vector2_<Real> Vector2r_;
|
||||
typedef Vector2_<int> Vector2i_;
|
||||
|
||||
template<typename T>
|
||||
struct Vector2;
|
||||
|
||||
typedef Vector2<double> Vector2d;
|
||||
typedef Vector2<float> Vector2f;
|
||||
typedef Vector2<Real> Vector2r;
|
||||
typedef Vector2<int> Vector2i;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
125
tjp/core/math/Vector2.hpp
Executable file
125
tjp/core/math/Vector2.hpp
Executable file
@@ -0,0 +1,125 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Vector2.h"
|
||||
#include "Zero.h"
|
||||
#include <tjp/core/types/Types.h>
|
||||
|
||||
#include <initializer_list>
|
||||
|
||||
namespace tjp::core::math {
|
||||
|
||||
template<typename Real>
|
||||
struct Vector2_ {
|
||||
using V = Real[2];
|
||||
V v;
|
||||
|
||||
Real &operator[](size_t i) { return v[i]; }
|
||||
Real const &operator[](size_t i) const { return v[i]; };
|
||||
} ;
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct Vector2
|
||||
{
|
||||
using Real = T;
|
||||
using V = Vector2_<Real>;
|
||||
V v;
|
||||
|
||||
constexpr Vector2(int zero) :
|
||||
v { (T)zero, (T)zero }
|
||||
{}
|
||||
|
||||
constexpr Vector2() = default;
|
||||
constexpr Vector2(const Vector2 &) = default;
|
||||
constexpr Vector2(const V &rhs) : v (rhs) {}
|
||||
constexpr Vector2(const std::initializer_list<Real> &v_)
|
||||
{
|
||||
auto i = 0;
|
||||
for (auto &n: v_)
|
||||
v[i++] = n;
|
||||
}
|
||||
|
||||
constexpr Vector2& operator=(const Vector2 &) = default;
|
||||
constexpr Vector2& operator=(const V &v_)
|
||||
{
|
||||
v = v_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr Vector2& operator=(const std::initializer_list<Real> &v_)
|
||||
{
|
||||
auto i = 0;
|
||||
for (auto &n: v_)
|
||||
v[i++] = n;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr Vector2(Real x, Real y)
|
||||
: v {x, y}
|
||||
{}
|
||||
|
||||
operator V &() { return v; }
|
||||
operator const V &() const { return v; }
|
||||
|
||||
T &x() { return v[0]; }
|
||||
T &y() { return v[1]; }
|
||||
|
||||
const T &x() const { return v[0]; }
|
||||
const T &y() const { return v[1]; }
|
||||
|
||||
template<typename U>
|
||||
Vector2<U> asType() const;
|
||||
|
||||
T lengthSquared () const;
|
||||
T length () const;
|
||||
|
||||
template<typename D=T>
|
||||
Vector2<D> normalize() const;
|
||||
|
||||
T &operator[](size_t i);
|
||||
const T &operator[](size_t i) const;
|
||||
|
||||
void flip ();
|
||||
|
||||
static const Vector2 Zero;
|
||||
} ;
|
||||
|
||||
template<typename Real>
|
||||
const Vector2<Real> Vector2<Real>::Zero = { zero<Real>(),zero<Real>() };
|
||||
|
||||
|
||||
template<typename Real>
|
||||
Real &Vector2<Real>::operator[](size_t i)
|
||||
{
|
||||
return v[i];
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
const Real &Vector2<Real>::operator[](size_t i) const
|
||||
{
|
||||
return v[i];
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
template<typename U>
|
||||
Vector2<U> Vector2<Real>::asType() const
|
||||
{
|
||||
return Vector2<U> { (U)x(), (U)y() };
|
||||
}
|
||||
|
||||
typedef Vector2<double> Vector2d;
|
||||
typedef Vector2<float> Vector2f;
|
||||
typedef Vector2<Real> Vector2r;
|
||||
typedef Vector2<int> Vector2i;
|
||||
|
||||
} // namespace
|
||||
|
||||
241
tjp/core/math/Vector2.inl
Executable file
241
tjp/core/math/Vector2.inl
Executable file
@@ -0,0 +1,241 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Vector2.hpp"
|
||||
|
||||
#include "Real.h"
|
||||
#include "Real.inl"
|
||||
|
||||
#include <utility>
|
||||
#include <initializer_list>
|
||||
#include "Zero.h"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
void zero(Vector2<Real> &v)
|
||||
{
|
||||
v = Vector2<Real>::Zero;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Vector2<Real> abs(const Vector2<Real> &v)
|
||||
{
|
||||
return { abs(v[0]), abs(v[1]) };
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Real lengthSquared(const Vector2<Real> &r)
|
||||
{
|
||||
return r.lengthSquared();
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Real length(const Vector2<Real> &r)
|
||||
{
|
||||
return r.length();
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Real Vector2<Real>::lengthSquared () const
|
||||
{
|
||||
Real x = v[0];
|
||||
Real y = v[1];
|
||||
return x*x + y*y;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Real Vector2<Real>::length () const
|
||||
{
|
||||
return sqrt(lengthSquared());
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
template<typename D>
|
||||
Vector2<D> Vector2<Real>::normalize() const
|
||||
{
|
||||
auto l = length();
|
||||
if (l == 0)
|
||||
return { D(0), D(0) };
|
||||
|
||||
return *this / l;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
void Vector2<Real>::flip ()
|
||||
{
|
||||
std::swap(v[0], v[1]);
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Real dot(Vector2<Real> const& l, Vector2<Real> const& r)
|
||||
{
|
||||
return l[0] * r[0] + l[1] * r[1];
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Vector2<Real> operator *(Real m, Vector2<Real> const& r)
|
||||
{
|
||||
return { m * r[0], m * r[1] };
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Vector2<Real> operator *(Vector2<Real> const& r, Real m)
|
||||
{
|
||||
return { m * r[0], m * r[1] };
|
||||
}
|
||||
|
||||
template<typename Real, typename U>
|
||||
Vector2<Real> operator /(U m, Vector2<Real> const& r)
|
||||
{
|
||||
return { m / r[0], m / r[1] };
|
||||
}
|
||||
|
||||
|
||||
template<typename Real>
|
||||
Vector2<Real> operator -(const Vector2<Real> &v)
|
||||
{
|
||||
return { -v[0], -v[1] };
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Vector2<Real> &operator +=(Vector2<Real> &v, const Vector2<Real> &r)
|
||||
{
|
||||
v[0] += r[0];
|
||||
v[1] += r[1];
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Vector2<Real> &operator -=(Vector2<Real> &v, const Vector2<Real> &r)
|
||||
{
|
||||
v[0] -= r[1];
|
||||
v[0] -= r[1];
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Vector2<Real> &operator /=(Vector2<Real> &v, Real r)
|
||||
{
|
||||
v[0] /= r;
|
||||
v[1] /= r;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Vector2<Real> &operator *=(Vector2<Real> &v, Real r)
|
||||
{
|
||||
v[0] *= r;
|
||||
v[1] *= r;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2_<T> operator -(const Vector2_<T> &l, const Vector2_<T> &r)
|
||||
{
|
||||
return { l[0] - r[0], l[1] - r[1] };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T> operator -(const Vector2<T> &l, const Vector2<T> &r)
|
||||
{
|
||||
return Vector2<T>(l.v - r.v);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T> operator +(const Vector2<T> &l, const Vector2<T> &r)
|
||||
{
|
||||
return { l[0] + r[0], l[1] + r[1] };
|
||||
}
|
||||
|
||||
template<typename T, typename X>
|
||||
Vector2<T> operator /(const Vector2<T> &p, const X &m)
|
||||
{
|
||||
return { T(p[0]/m), T(p[1]/m) };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T> cross(const Vector2<T> &l, const Vector2<T> &r);
|
||||
|
||||
template<typename T>
|
||||
Vector2<T> multiply(const Vector2<T> &l, const Vector2<T> &r)
|
||||
{
|
||||
return { l[0] * r[0], l[1] * r[1] };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T> mul(const Vector2<T> &l, const Vector2<T> &r)
|
||||
{
|
||||
return multiply(l, r);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T> divide(const Vector2<T> &l, const Vector2<T> &r)
|
||||
{
|
||||
return { l[0] / r[0], l[1] / r[1] };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T> operator /(const Vector2<T> &l, const Vector2<T> &r)
|
||||
{
|
||||
return { l[0] / r[0], l[1] / r[1] };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool operator !=(const Vector2_<T> &l, const Vector2_<T> &r)
|
||||
{
|
||||
return
|
||||
l[0] != r[0] ||
|
||||
l[1] != r[1];
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
bool operator ==(const Vector2_<T> &l, const Vector2_<T> &r)
|
||||
{
|
||||
return
|
||||
l[0] == r[0] &&
|
||||
l[1] == r[1];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool operator !=(const Vector2<T> &l, const Vector2<T> &r) { return l.v != r.v; }
|
||||
|
||||
template<typename T>
|
||||
bool operator ==(const Vector2<T> &l, const Vector2<T> &r) { return l.v == r.v; }
|
||||
|
||||
template<typename Real>
|
||||
Vector2<Real> fract(const Vector2<Real> &v)
|
||||
{
|
||||
return {
|
||||
fract(v[0]),
|
||||
fract(v[1])
|
||||
};
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Vector2<Real> trunc(const Vector2<Real> &v)
|
||||
{
|
||||
return {
|
||||
trunc(v[0]),
|
||||
trunc(v[1])
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
35
tjp/core/math/Vector3.h
Executable file
35
tjp/core/math/Vector3.h
Executable file
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Real.h"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
struct Vector3_;
|
||||
|
||||
typedef Vector3_<double> Vector3d_;
|
||||
typedef Vector3_<float> Vector3f_;
|
||||
typedef Vector3_<Real> Vector3r_;
|
||||
|
||||
template<typename Real>
|
||||
struct Vector3;
|
||||
|
||||
typedef Vector3<double> Vector3d;
|
||||
typedef Vector3<float> Vector3f;
|
||||
typedef Vector3<Real> Vector3r;
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
118
tjp/core/math/Vector3.hpp
Executable file
118
tjp/core/math/Vector3.hpp
Executable file
@@ -0,0 +1,118 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Vector3.h"
|
||||
#include "Zero.h"
|
||||
#include <tjp/core/types/Types.h>
|
||||
#include <tjp/core/containers/Pack.h>
|
||||
|
||||
#include <tjp/core/assert/debug_assert.h>
|
||||
#include <initializer_list>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
struct Vector3_ {
|
||||
using V = Real[3];
|
||||
V v;
|
||||
|
||||
Real &operator[](size_t i) { return v[i]; }
|
||||
Real const &operator[](size_t i) const { return v[i]; };
|
||||
} ;
|
||||
|
||||
template<typename T>
|
||||
struct Vector3
|
||||
{
|
||||
using Real = T;
|
||||
using V = Vector3_<Real>;
|
||||
V v;
|
||||
|
||||
constexpr Vector3(int zero) :
|
||||
v { static_cast<T>(zero), static_cast<T>(zero), static_cast<T>(zero) }
|
||||
{}
|
||||
|
||||
constexpr Vector3() = default;
|
||||
constexpr Vector3(const Vector3 &) = default;
|
||||
constexpr Vector3(const V &rhs) : v (rhs) {}
|
||||
constexpr Vector3(const std::initializer_list<Real> &v_)
|
||||
{
|
||||
auto i = 0;
|
||||
for (auto &n: v_)
|
||||
v[i++] = n;
|
||||
}
|
||||
|
||||
constexpr Vector3& operator=(const Vector3 &) = default;
|
||||
constexpr Vector3& operator=(const V &v_)
|
||||
{
|
||||
v = v_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr Vector3(Real x, Real y, Real z)
|
||||
: v {x, y, z}
|
||||
{}
|
||||
|
||||
operator V()
|
||||
{
|
||||
return { v[0], v[1], v[2] };
|
||||
}
|
||||
|
||||
Real length () const;
|
||||
Real lengthSquared () const;
|
||||
Vector3 normalize () const;
|
||||
|
||||
Vector3 operator -() const;
|
||||
Vector3 &operator +=(const Vector3 &r);
|
||||
Vector3 &operator -=(const Vector3 &r);
|
||||
|
||||
Vector3 &operator /=(Real r);
|
||||
Vector3 &operator *=(Real r);
|
||||
|
||||
Real &operator[](size_t size);
|
||||
Real const &operator[](size_t size) const;
|
||||
|
||||
template<typename U>
|
||||
Vector3<U> asType() const;
|
||||
|
||||
static const Vector3 Zero;
|
||||
} ;
|
||||
|
||||
template<typename Real>
|
||||
const Vector3<Real> Vector3<Real>::Zero = { zero<Real>(),zero<Real>(),zero<Real>() };
|
||||
|
||||
template<typename Real>
|
||||
Real &Vector3<Real>::operator[](size_t size)
|
||||
{
|
||||
return v[size];
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Real const &Vector3<Real>::operator[](size_t size) const
|
||||
{
|
||||
return v[size];
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
template<typename U>
|
||||
Vector3<U> Vector3<Real>::asType() const
|
||||
{
|
||||
return Vector3<U> { (U)v[0], (U)v[1], (U)v[2] };
|
||||
}
|
||||
|
||||
typedef Vector3<double> Vector3d;
|
||||
typedef Vector3<float> Vector3f;
|
||||
typedef Vector3<Real> Vector3r;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
285
tjp/core/math/Vector3.inl
Executable file
285
tjp/core/math/Vector3.inl
Executable file
@@ -0,0 +1,285 @@
|
||||
//
|
||||
// Math.inl
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Vector3.hpp"
|
||||
#include "Zero.h"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
Real lengthSquared(const Vector3<Real> &r)
|
||||
{
|
||||
return r.lengthSquared();
|
||||
}
|
||||
|
||||
|
||||
template<typename Real>
|
||||
Real length(const Vector3<Real> &r)
|
||||
{
|
||||
return r.length();
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
void zero(Vector3<Real> &v)
|
||||
{
|
||||
v = Vector3<Real>::Zero;
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Real Vector3<Real>::length () const
|
||||
{
|
||||
return sqrt(lengthSquared());
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Real Vector3<Real>::lengthSquared() const
|
||||
{
|
||||
return v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Vector3<Real> Vector3<Real>::normalize () const
|
||||
{
|
||||
return *this / length();
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real, typename U>
|
||||
Vector3<Real> operator *(const Vector3<Real> &l, U r)
|
||||
{
|
||||
return Vector3<Real> {
|
||||
l[0] * r,
|
||||
l[1] * r,
|
||||
l[2] * r
|
||||
};
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Vector3<Real> mul(const Vector3<Real> &l, const Vector3<Real> &r)
|
||||
{
|
||||
return { l[0] * r[0], l[1] * r[1], l[2] * r[2]};
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real, typename U>
|
||||
Vector3<Real> operator /(const Vector3<Real> &l, U r)
|
||||
{
|
||||
return Vector3<Real> {
|
||||
l[0] / r,
|
||||
l[1] / r,
|
||||
l[2] / r
|
||||
};
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real, typename U>
|
||||
Vector3<Real> operator *(U l, const Vector3<Real> &r)
|
||||
{
|
||||
return r * l;
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real, typename U>
|
||||
Vector3<Real> operator /(U l, const Vector3<Real> &r)
|
||||
{
|
||||
return Vector3<Real> {
|
||||
l / r[0],
|
||||
l / r[1],
|
||||
l / r[2]
|
||||
};
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Vector3<Real> div(const Vector3<Real> &l, const Vector3<Real> &r)
|
||||
{
|
||||
return { l[0] / r[0], l[1] / r[1], l[2] / r[2] };
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Vector3<Real> Vector3<Real>::operator -() const
|
||||
{
|
||||
return { -v[0], -v[1], -v[2] };
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Vector3_<Real> operator +(const Vector3_<Real> &l, const Vector3_<Real> &r)
|
||||
{
|
||||
return { l[0] + r[0], l[1] + r[1], l[2] + r[2] };
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Vector3<Real> operator +(const Vector3<Real> &l, const Vector3<Real> &r)
|
||||
{
|
||||
return l.v + r.v;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Vector3_<Real> operator -(const Vector3_<Real> &l, const Vector3_<Real> &r)
|
||||
{
|
||||
return { l[0] - r[0], l[1] - r[1], l[2] - r[2] };
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Vector3<Real> operator -(const Vector3<Real> &l, const Vector3<Real> &r)
|
||||
{
|
||||
return l.v - r.v;
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Vector3<Real> &Vector3<Real>::operator +=(const Vector3<Real> &r)
|
||||
{
|
||||
v[0] += r.v[0];
|
||||
v[1] += r.v[1];
|
||||
v[2] += r.v[2];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Vector3<Real> &Vector3<Real>::operator -=(const Vector3<Real> &r)
|
||||
{
|
||||
v[0] -= r.v[0];
|
||||
v[1] -= r.v[1];
|
||||
v[2] -= r.v[2];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Vector3<Real> &Vector3<Real>::operator /=(Real r)
|
||||
{
|
||||
v[0] /= r;
|
||||
v[1] /= r;
|
||||
v[2] /= r;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Vector3<Real> &Vector3<Real>::operator *=(Real r)
|
||||
{
|
||||
v[0] *= r;
|
||||
v[1] *= r;
|
||||
v[2] *= r;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Real dot(Vector3<Real> const& l, Vector3<Real> const& r)
|
||||
{
|
||||
return l[0] * r[0] + l[1] * r[1] + l[2] * r[2];
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Vector3<Real> cross(Vector3<Real> const& v0, Vector3<Real> const& v1)
|
||||
{
|
||||
Vector3<Real> result = Vector3<Real>::Zero;
|
||||
result[0] = v0[1] * v1[2] - v0[2] * v1[1];
|
||||
result[1] = v0[2] * v1[0] - v0[0] * v1[2];
|
||||
result[2] = v0[0] * v1[1] - v0[1] * v1[0];
|
||||
return result;
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Vector3<Real> operator ^(Vector3<Real> const& v0, Vector3<Real> const& v1)
|
||||
{
|
||||
return cross(v0, v1);
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
bool operator ==(const Vector3_<Real> &l, const Vector3_<Real> &r)
|
||||
{
|
||||
return
|
||||
l[0] == r[0] &&
|
||||
l[1] == r[1] &&
|
||||
l[2] == r[2];
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
bool operator !=(const Vector3_<Real> &l, const Vector3_<Real> &r)
|
||||
{
|
||||
return
|
||||
l[0] != r[0] ||
|
||||
l[1] != r[1] ||
|
||||
l[2] != r[2];
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
bool operator !=(const Vector3<Real> &l, const Vector3<Real> &r) { return l.v != r.v; }
|
||||
|
||||
template<typename Real>
|
||||
bool operator ==(const Vector3<Real> &l, const Vector3<Real> &r) { return l.v == r.v; }
|
||||
|
||||
template<typename Real>
|
||||
bool operator<(const Vector3<Real> &l, const Vector3<Real> &r)
|
||||
{
|
||||
if (l[0] < r[0]) return true;
|
||||
if (l[0] > r[0]) return false;
|
||||
if (l[1] < r[1]) return true;
|
||||
if (l[1] > r[1]) return false;
|
||||
if (l[2] < r[2]) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Real operator *(const Vector3<Real> &l, const Vector3<Real> &r)
|
||||
{
|
||||
return dot(l, r);
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Vector3<Real> fract(const Vector3<Real> &v)
|
||||
{
|
||||
return {
|
||||
fract(v[0]),
|
||||
fract(v[1]),
|
||||
fract(v[2])
|
||||
};
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Vector3<Real> trunc(const Vector3<Real> &v)
|
||||
{
|
||||
return {
|
||||
trunc(v[0]),
|
||||
trunc(v[1]),
|
||||
trunc(v[2])
|
||||
};
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Real distance_relative(const Vector3<Real> &l, const Vector3<Real> &r)
|
||||
{
|
||||
return distance_squared(l, r);
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
28
tjp/core/math/Vector4.h
Executable file
28
tjp/core/math/Vector4.h
Executable file
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Real.h"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename T>
|
||||
struct Vector4;
|
||||
|
||||
typedef Vector4<double> Vector4d;
|
||||
typedef Vector4<float> Vector4f;
|
||||
typedef Vector4<Real> Vector4r;
|
||||
typedef Vector4<int> Vector4i;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
137
tjp/core/math/Vector4.hpp
Executable file
137
tjp/core/math/Vector4.hpp
Executable file
@@ -0,0 +1,137 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Vector4.h"
|
||||
#include "Vector3.h"
|
||||
#include "Zero.h"
|
||||
#include <tjp/core/containers/Tuple.h>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
template<typename Real>
|
||||
struct Vector4_ {
|
||||
using V = Real[4];
|
||||
V v;
|
||||
|
||||
Real &operator[](size_t i) { return v[i]; }
|
||||
Real const &operator[](size_t i) const { return v[i]; };
|
||||
} ;
|
||||
|
||||
template<typename T>
|
||||
struct Vector4
|
||||
{
|
||||
using Real = T;
|
||||
using V = Vector4_<Real>;
|
||||
V v;
|
||||
|
||||
constexpr Vector4(int zero) :
|
||||
v { static_cast<T>(zero), static_cast<T>(zero), static_cast<T>(zero) }
|
||||
{}
|
||||
|
||||
constexpr Vector4() = default;
|
||||
constexpr Vector4(const Vector4 &) = default;
|
||||
constexpr Vector4(const V &rhs) : v (rhs) {}
|
||||
constexpr Vector4(const std::initializer_list<Real> &v_)
|
||||
{
|
||||
auto i = 0;
|
||||
for (auto &n: v_)
|
||||
v[i++] = n;
|
||||
}
|
||||
|
||||
constexpr Vector4& operator=(const Vector4 &) = default;
|
||||
constexpr Vector4& operator=(const V &v_)
|
||||
{
|
||||
v = v_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr Vector4(const Vector3_<T> &v3, Real w)
|
||||
: v {v3[0], v3[1], v3[2], w}
|
||||
{}
|
||||
|
||||
constexpr Vector4(Real x, Real y, Real z, Real w)
|
||||
: v {x, y, z, w}
|
||||
{}
|
||||
|
||||
operator V()
|
||||
{
|
||||
return { v[0], v[1], v[2], v[3] };
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
Vector4<U> asType() const
|
||||
{
|
||||
return Vector4<U> { (U)v[0], (U)v[1], (U)v[2], (U)v[3] };
|
||||
}
|
||||
|
||||
Tuple<Vector3<T>, T> as3p1() const
|
||||
{
|
||||
return {
|
||||
Vector3<T> { v[0], v[1], v[2] },
|
||||
v[3]
|
||||
};
|
||||
}
|
||||
|
||||
T &operator[](size_t i)
|
||||
{
|
||||
return v[i];
|
||||
}
|
||||
|
||||
const T &operator[](size_t i) const
|
||||
{
|
||||
return v[i];
|
||||
}
|
||||
|
||||
Vector3<T> xyz() const
|
||||
{
|
||||
return {v[0], v[1], v[2] };
|
||||
}
|
||||
|
||||
Real w() const
|
||||
{
|
||||
return v[3];
|
||||
}
|
||||
|
||||
// operator bool() const
|
||||
// {
|
||||
// return
|
||||
// v[0] != 0 ||
|
||||
// v[1] != 0 ||
|
||||
// v[2] != 0 ||
|
||||
// v[3] != 0;
|
||||
// }
|
||||
//
|
||||
// bool operator!() const
|
||||
// {
|
||||
// return
|
||||
// v[0] == 0 &&
|
||||
// v[1] == 0 &&
|
||||
// v[2] == 0 &&
|
||||
// v[3] == 0;
|
||||
// }
|
||||
|
||||
public:
|
||||
static const Vector4 Zero;
|
||||
} ;
|
||||
|
||||
template<typename Real>
|
||||
const Vector4<Real> Vector4<Real>::Zero = {
|
||||
zero<Real>(),
|
||||
zero<Real>(),
|
||||
zero<Real>(),
|
||||
zero<Real>()
|
||||
};
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
154
tjp/core/math/Vector4.inl
Executable file
154
tjp/core/math/Vector4.inl
Executable file
@@ -0,0 +1,154 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Vector4.hpp"
|
||||
#include "Vector3.hpp"
|
||||
#include "Real.inl"
|
||||
|
||||
namespace tjp::core::math {
|
||||
|
||||
template<typename Real>
|
||||
bool operator ==(const Vector4_<Real> &l, const Vector4_<Real> &r)
|
||||
{
|
||||
return
|
||||
l[0] == r[0] &&
|
||||
l[1] == r[1] &&
|
||||
l[2] == r[2] &&
|
||||
l[3] == r[3];
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
bool operator !=(const Vector4_<Real> &l, const Vector4_<Real> &r)
|
||||
{
|
||||
return
|
||||
l[0] != r[0] ||
|
||||
l[1] != r[1] ||
|
||||
l[2] != r[2] ||
|
||||
l[3] != r[3];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool operator !=(const Vector4<T> &l, const Vector4<T> &r) { return l.v != r.v; }
|
||||
|
||||
template<typename T>
|
||||
bool operator ==(const Vector4<T> &l, const Vector4<T> &r) { return l.v == r.v; }
|
||||
|
||||
|
||||
template<typename Real>
|
||||
void zero(Vector4<Real> &v)
|
||||
{
|
||||
v = Vector4<Real>(0,0,0,0);
|
||||
}
|
||||
|
||||
//template<typename Real>
|
||||
//Vector4<Real> Vector4_(const Vector3<Real> &l, const float a)
|
||||
//{
|
||||
// return { l[0], l[1], l[2], a };
|
||||
//}
|
||||
|
||||
template<typename Real>
|
||||
Vector4<Real> operator +(const Vector4<Real> &l, const Vector4<Real> &r)
|
||||
{
|
||||
return { l[0] + r[0], l[1] + r[1], l[2] + r[2], l[3] + r[3] };
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real>
|
||||
Vector4<Real> operator -(const Vector4<Real> &l, const Vector4<Real> &r)
|
||||
{
|
||||
return { l[0] - r[0], l[1] - r[1], l[2] - r[2], l[3] + r[3] };
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
void operator -=(Vector4<Real> &l, const Vector4<Real> &r)
|
||||
{
|
||||
l[0] -= r[0];
|
||||
l[1] -= r[1];
|
||||
l[2] -= r[2];
|
||||
l[3] -= r[3];
|
||||
}
|
||||
|
||||
// inline
|
||||
template<typename Real, typename U>
|
||||
Vector4<Real> operator *(const Vector4<Real> &l, U r)
|
||||
{
|
||||
return Vector4<Real> {
|
||||
l[0] * r,
|
||||
l[1] * r,
|
||||
l[2] * r,
|
||||
l[3] * r
|
||||
};
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Real dot(const Vector4<Real> &l, const Vector4<Real> &r)
|
||||
{
|
||||
return
|
||||
l[0] * r[0] +
|
||||
l[1] * r[1] +
|
||||
l[2] * r[2] +
|
||||
l[3] * r[3]
|
||||
;
|
||||
}
|
||||
|
||||
template<typename Real, typename U>
|
||||
Vector4<Real> operator *(U r, const Vector4<Real> &l)
|
||||
{
|
||||
return l * r;
|
||||
}
|
||||
|
||||
template<typename Real, typename U>
|
||||
Vector4<Real> operator /(U l, const Vector4<Real> &r)
|
||||
{
|
||||
return {
|
||||
l/r[0],
|
||||
l/r[1],
|
||||
l/r[2],
|
||||
l/r[3]
|
||||
};
|
||||
}
|
||||
|
||||
template<typename Real, typename U>
|
||||
Vector4<Real> operator /(const Vector4<Real> &l, U r)
|
||||
{
|
||||
return {
|
||||
l[0]/r,
|
||||
l[1]/r,
|
||||
l[2]/r,
|
||||
l[3]/r
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
template<typename Real>
|
||||
Vector4<Real> fract(const Vector4<Real> &v)
|
||||
{
|
||||
return {
|
||||
fract(v[0]),
|
||||
fract(v[1]),
|
||||
fract(v[2]),
|
||||
fract(v[3])
|
||||
};
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
Vector4<Real> trunc(const Vector4<Real> &v)
|
||||
{
|
||||
return {
|
||||
trunc(v[0]),
|
||||
trunc(v[1]),
|
||||
trunc(v[2]),
|
||||
trunc(v[3])
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
33
tjp/core/math/Zero.h
Executable file
33
tjp/core/math/Zero.h
Executable file
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp::core::math {
|
||||
|
||||
template<typename T>
|
||||
void zero(T &t)
|
||||
{
|
||||
t = T{0};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T zero()
|
||||
{
|
||||
T t;
|
||||
zero(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool is_zero(const T &t)
|
||||
{
|
||||
return t == zero<T>();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
50
tjp/core/math/_delete/BigDecimal+IO+Test.cpp
Normal file
50
tjp/core/math/_delete/BigDecimal+IO+Test.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#include "BigDecimal+IO.h"
|
||||
|
||||
#include <tjp/core/io/bin/IO.h>
|
||||
#include <tjp/core/io/json/in_sajson.h>
|
||||
#include <tjp/core/io/json/out.h>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
namespace test {
|
||||
|
||||
SCENARIO("big decimal io")
|
||||
{
|
||||
GIVEN("a number")
|
||||
{
|
||||
auto a = BigDecimal::fromSignificandExponent(10923905823095,-5);
|
||||
|
||||
WHEN("bin")
|
||||
{
|
||||
auto s = io::bin::serialize(a);
|
||||
auto b = io::bin::deserialize<BigDecimal>(s);
|
||||
|
||||
REQUIRE(a == b);
|
||||
}
|
||||
|
||||
WHEN("json")
|
||||
{
|
||||
auto s = io::json::serialize(a);
|
||||
auto b = io::json::deserialize<BigDecimal>(s);
|
||||
|
||||
REQUIRE(a == b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
60
tjp/core/math/_delete/BigDecimal+IO.cpp
Executable file
60
tjp/core/math/_delete/BigDecimal+IO.cpp
Executable file
@@ -0,0 +1,60 @@
|
||||
//
|
||||
// Math.cpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#include "BigDecimal+IO.h"
|
||||
|
||||
#include <tjp/core/string/to_string.hpp>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
std::ostream &operator <<(std::ostream &o, const BigDecimal &m)
|
||||
{
|
||||
std::string num_ = core::to_string(m.significand);
|
||||
std::string_view num = num_;
|
||||
|
||||
auto leading = (s32)num.length() + m.exp;
|
||||
if (leading <= 0)
|
||||
{
|
||||
o << "0.";
|
||||
while (leading++ < 0)
|
||||
o << "0";
|
||||
|
||||
o << num;
|
||||
|
||||
return o;
|
||||
}
|
||||
else
|
||||
{
|
||||
s32 lastNonZero = num.size();
|
||||
for (; lastNonZero>0; --lastNonZero)
|
||||
if (num[lastNonZero-1] != '0')
|
||||
break;
|
||||
|
||||
auto left = std::min(lastNonZero, leading);
|
||||
auto right = lastNonZero - left;
|
||||
auto zeros = leading - lastNonZero;
|
||||
|
||||
o << num.substr(0, left);
|
||||
|
||||
if (right > 0)
|
||||
o << ".";
|
||||
|
||||
o << num.substr(left, right);
|
||||
|
||||
while (zeros-- > 0)
|
||||
o << "0";
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
41
tjp/core/math/_delete/BigDecimal+IO.h
Normal file
41
tjp/core/math/_delete/BigDecimal+IO.h
Normal file
@@ -0,0 +1,41 @@
|
||||
//
|
||||
// MathIO.h
|
||||
// common
|
||||
//
|
||||
// Created by Timothy Prepscius on 8/4/18.
|
||||
// Copyright © 2018 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BigDecimal.hpp"
|
||||
#include "BigInt+IO.h"
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
std::ostream &operator <<(std::ostream &o, const BigDecimal &m);
|
||||
|
||||
template<typename IO>
|
||||
void io_(IO &io, BigDecimal &v)
|
||||
{
|
||||
io.object("significand", v.significand, "exp", v.exp);
|
||||
|
||||
#ifdef DEBUG_BIGDECIMAL
|
||||
generateDebug(v);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename IO>
|
||||
void io_bin(IO &io, BigDecimal &v) { return io_(io, v); }
|
||||
|
||||
template<typename IO>
|
||||
void io_json(IO &io, BigDecimal &v) { return io_(io, v); }
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
194
tjp/core/math/_delete/BigDecimal+Test.cpp
Executable file
194
tjp/core/math/_delete/BigDecimal+Test.cpp
Executable file
@@ -0,0 +1,194 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#include "BigDecimal.h"
|
||||
#include "BigDecimal+IO.h"
|
||||
|
||||
#include "Algorithm.hpp"
|
||||
|
||||
#include <tjp/core/string/to_string.hpp>
|
||||
#include <tjp/core/string/starts_with.hpp>
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
namespace test {
|
||||
|
||||
SCENARIO("big decimal")
|
||||
{
|
||||
auto a3_5 = BigDecimal::fromIntegerDecimalExponent(3,5);
|
||||
auto a3_5124124 = BigDecimal::fromIntegerDecimalExponent(3,5124124);
|
||||
auto a0_005124124 = BigDecimal::fromIntegerDecimalExponent(5,124124,-3);
|
||||
auto a0_006124124 = BigDecimal::fromIntegerDecimalExponent(6,124124,-3);
|
||||
auto a30000 = BigDecimal::fromIntegerDecimalExponent(3,0,4);
|
||||
auto a30001 = BigDecimal::fromIntegerDecimalExponent(30001,0);
|
||||
auto a30000_2 = BigDecimal::fromIntegerDecimalExponent(30000,2);
|
||||
|
||||
GIVEN("a number")
|
||||
{
|
||||
REQUIRE(core::to_string(a3_5) == "3.5");
|
||||
REQUIRE(core::to_string(a3_5124124) == "3.5124124");
|
||||
REQUIRE(core::to_string(a0_005124124) == "0.005124124");
|
||||
REQUIRE(core::to_string(a0_006124124) == "0.006124124");
|
||||
REQUIRE(core::to_string(a30000) == "30000");
|
||||
REQUIRE(core::to_string(a30001) == "30001");
|
||||
REQUIRE(core::to_string(a30000_2) == "30000.2");
|
||||
|
||||
REQUIRE(core::to_string(a30000/1) == "30000");
|
||||
}
|
||||
|
||||
GIVEN("a number")
|
||||
{
|
||||
REQUIRE(a3_5.getInteger() == 3);
|
||||
REQUIRE(a3_5124124.getInteger() == 3);
|
||||
REQUIRE(a0_005124124.getInteger() == 0);
|
||||
REQUIRE(a30000.getInteger() == 30000);
|
||||
REQUIRE(a30000_2.getInteger() == 30000);
|
||||
|
||||
auto a_5 = BigDecimal::fromIntegerDecimalExponent(0,5);
|
||||
auto a_5124124 = BigDecimal::fromIntegerDecimalExponent(0,5124124);
|
||||
auto a_005124124 = BigDecimal::fromIntegerDecimalExponent(0,5124124, -2);
|
||||
auto a_0 = BigDecimal();
|
||||
auto a_2 = BigDecimal::fromIntegerDecimalExponent(0,2);
|
||||
|
||||
REQUIRE(a3_5.getDecimal() == a_5);
|
||||
REQUIRE(a3_5124124.getDecimal() == a_5124124);
|
||||
REQUIRE(a0_005124124.getDecimal() == a_005124124);
|
||||
REQUIRE(a30000.getDecimal() == a_0);
|
||||
REQUIRE(a30000_2.getDecimal() == a_2);
|
||||
}
|
||||
GIVEN("reals")
|
||||
{
|
||||
auto b30001 = BigDecimal(30001);
|
||||
auto b3_5 = BigDecimal(3.5);
|
||||
auto b3_5124124 = BigDecimal(3.5124124);
|
||||
auto b0_005124124 = BigDecimal(0.005124124);
|
||||
auto b0_006124124 = BigDecimal(0.006124124);
|
||||
|
||||
auto b30001_s = core::to_string(b30001);
|
||||
|
||||
auto sigma = BigDecimal(0.0001);
|
||||
REQUIRE(distance(a3_5, b3_5) < sigma);
|
||||
REQUIRE(distance(a3_5124124, b3_5124124) < sigma);
|
||||
REQUIRE(distance(a0_005124124, b0_005124124) < sigma);
|
||||
REQUIRE(distance(a0_006124124, b0_006124124) < sigma);
|
||||
|
||||
REQUIRE(distance(a30001, b30001) < sigma);
|
||||
}
|
||||
|
||||
GIVEN("numbers")
|
||||
{
|
||||
auto b3_5 = BigDecimal::fromIntegerDecimalExponent(3,5);
|
||||
|
||||
REQUIRE (a3_5 < a3_5124124);
|
||||
REQUIRE (a3_5 <= a3_5124124);
|
||||
REQUIRE (a3_5124124 > a3_5);
|
||||
|
||||
REQUIRE (a0_005124124 < a0_006124124);
|
||||
REQUIRE (a0_005124124 <= a0_006124124);
|
||||
REQUIRE (a0_006124124 > a0_005124124);
|
||||
|
||||
REQUIRE (a3_5 <= b3_5);
|
||||
}
|
||||
|
||||
GIVEN("a number")
|
||||
{
|
||||
auto a = BigDecimal::fromIntegerDecimalExponent(3,5);
|
||||
auto b = BigDecimal::fromIntegerDecimalExponent(7,3);
|
||||
|
||||
auto a_ = core::to_string(a);
|
||||
auto b_ = core::to_string(b);
|
||||
|
||||
WHEN("add")
|
||||
{
|
||||
auto c = a + b;
|
||||
auto c_ = core::to_string(c);
|
||||
|
||||
REQUIRE(c == BigDecimal::fromIntegerDecimalExponent(10,8));
|
||||
}
|
||||
|
||||
WHEN("multiply")
|
||||
{
|
||||
auto c = a / b;
|
||||
auto c_ = core::to_string(c);
|
||||
|
||||
auto c_s = std::string("0.4794");
|
||||
REQUIRE(core::starts_with(c_, c_s));
|
||||
|
||||
}
|
||||
|
||||
WHEN("divide")
|
||||
{
|
||||
auto c = a * b;
|
||||
auto c_ = core::to_string(c);
|
||||
|
||||
REQUIRE(c == BigDecimal::fromIntegerDecimalExponent(25, 55));
|
||||
}
|
||||
|
||||
WHEN("sqrt")
|
||||
{
|
||||
auto a = BigDecimal::fromIntegerDecimalExponent(20,25);
|
||||
auto b = sqrt(a);
|
||||
|
||||
auto a_ = core::to_string(a);
|
||||
auto b_ = core::to_string(b);
|
||||
|
||||
REQUIRE(b == BigDecimal::fromIntegerDecimalExponent(4,5));
|
||||
|
||||
auto c = BigDecimal::fromIntegerDecimalExponent(300000,0,-5);
|
||||
|
||||
auto s = std::sqrt(3.0);
|
||||
auto d_s = std::string("1.73205");
|
||||
|
||||
auto d = sqrt(c);
|
||||
auto d_ = core::to_string(d);
|
||||
|
||||
REQUIRE(core::starts_with(d_, d_s));
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN("a number to reduce")
|
||||
{
|
||||
auto a = BigDecimal::fromIntegerDecimalExponent(100,0,0);
|
||||
auto b = BigDecimal::fromIntegerDecimalExponent(1,0,2);
|
||||
|
||||
REQUIRE(a == b);
|
||||
reduce(a);
|
||||
|
||||
auto a_ = core::to_string(a);
|
||||
auto b_ = core::to_string(b);
|
||||
|
||||
REQUIRE(a == b);
|
||||
REQUIRE(a.significand == 1);
|
||||
REQUIRE(a.exp == b.exp);
|
||||
REQUIRE(a.significand == b.significand);
|
||||
}
|
||||
|
||||
GIVEN("a number to reduce < 1")
|
||||
{
|
||||
auto a = BigDecimal::fromIntegerDecimalExponent(100,0,-4);
|
||||
auto b = BigDecimal::fromIntegerDecimalExponent(1,0,-2);
|
||||
REQUIRE(a == b);
|
||||
reduce(a);
|
||||
|
||||
auto a_ = core::to_string(a);
|
||||
auto b_ = core::to_string(b);
|
||||
|
||||
REQUIRE(a == b);
|
||||
REQUIRE(a.significand == 1);
|
||||
REQUIRE(a.exp == b.exp);
|
||||
REQUIRE(a.significand == b.significand);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
353
tjp/core/math/_delete/BigDecimal.cpp
Executable file
353
tjp/core/math/_delete/BigDecimal.cpp
Executable file
@@ -0,0 +1,353 @@
|
||||
//
|
||||
// Math.cpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#include "BigDecimal.hpp"
|
||||
#include "BigDecimal+IO.h"
|
||||
#include <tjp/core/string/to_string.hpp>
|
||||
#include <tjp/core/assert/debug_assert.h>
|
||||
#include <tjp/core/debug/Debug.h>
|
||||
|
||||
#include "Real.inl"
|
||||
#include "BigInt+Imp.hpp"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
BigDecimal BigDecimal::Zero(0);
|
||||
|
||||
// -------
|
||||
|
||||
static BigInt::Imp::V ten(10);
|
||||
double sqrt_10 = sqrt(10.0);
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define DEBUG_BIGDECIMAL
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_BIGDECIMAL
|
||||
void generateDebug(BigDecimal &d)
|
||||
{
|
||||
d.debug = core::to_string(d);
|
||||
}
|
||||
#endif
|
||||
|
||||
void reduce(BigDecimal &v)
|
||||
{
|
||||
while (!is_zero(v.significand) && is_zero(v.significand % 10))
|
||||
{
|
||||
v.significand /= 10;
|
||||
v.exp++;
|
||||
}
|
||||
|
||||
generateDebug(v);
|
||||
}
|
||||
|
||||
size_t numDigits(const BigInt &v_)
|
||||
{
|
||||
if (is_zero(v_))
|
||||
return 0;
|
||||
|
||||
auto v = v_;
|
||||
size_t length = 0;
|
||||
while (!is_zero(v))
|
||||
{
|
||||
v /= 10;
|
||||
length++;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
// -------
|
||||
|
||||
BigDecimal::BigDecimal() :
|
||||
exp(0)
|
||||
{
|
||||
generateDebug(*this);
|
||||
}
|
||||
|
||||
BigDecimal::BigDecimal(const math::Real &real) :
|
||||
BigDecimal(real, 16)
|
||||
{}
|
||||
|
||||
BigDecimal::BigDecimal(const math::Real &real, s32 precision)
|
||||
{
|
||||
long double d = real;
|
||||
d *= std::pow(10.0, precision);
|
||||
|
||||
auto d_ = std::to_string(d);
|
||||
|
||||
std::string_view v = d_;
|
||||
|
||||
debug_assert(v.find('E') == -1);
|
||||
v = v.substr(0, v.find('.'));
|
||||
|
||||
long i = v.size()-1;
|
||||
for (; i>=0; --i)
|
||||
{
|
||||
if (v[i] != '0')
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < 0 || (v[i] == '-'))
|
||||
{
|
||||
exp = 0;
|
||||
|
||||
generateDebug(*this);
|
||||
return;
|
||||
}
|
||||
|
||||
precision -= (v.size()-1 - i);
|
||||
significand = BigInt(v.substr(0, i+1));
|
||||
exp = -precision;
|
||||
|
||||
generateDebug(*this);
|
||||
}
|
||||
|
||||
BigDecimal::BigDecimal(BigInt &&significand_, s32 exp_) :
|
||||
significand(significand_),
|
||||
exp(exp_)
|
||||
{
|
||||
generateDebug(*this);
|
||||
}
|
||||
|
||||
BigDecimal::BigDecimal(const BigInt &integer, const BigInt &decimal, s32 exp_)
|
||||
{
|
||||
auto precision = (s32)numDigits(decimal);
|
||||
auto m = boost::multiprecision::pow(ten, precision);
|
||||
significand = BigInt::Imp { m * integer.imp->v + decimal.imp->v };
|
||||
exp = exp_ - precision;
|
||||
|
||||
generateDebug(*this);
|
||||
}
|
||||
|
||||
// ------------------
|
||||
|
||||
BigDecimal BigDecimal::fromInteger(BigInt &&significand_)
|
||||
{
|
||||
return fromSignificandExponent(std::move(significand_), 0);
|
||||
}
|
||||
|
||||
|
||||
BigDecimal BigDecimal::fromReal(math::Real real, int precision)
|
||||
{
|
||||
return BigDecimal(real, precision);
|
||||
}
|
||||
|
||||
BigDecimal BigDecimal::fromIntegerDecimalExponent(const BigInt &integer, const BigInt &decimal, s32 exp)
|
||||
{
|
||||
return BigDecimal(integer, decimal, exp);
|
||||
}
|
||||
|
||||
BigDecimal BigDecimal::fromSignificandExponent(BigInt &&significand, s32 exp)
|
||||
{
|
||||
return BigDecimal(std::move(significand), exp);
|
||||
}
|
||||
|
||||
BigInt BigDecimal::getInteger() const
|
||||
{
|
||||
auto m = boost::multiprecision::pow(ten, std::abs(exp));
|
||||
if (exp > 0)
|
||||
return BigInt::Imp { m * significand.imp->v };
|
||||
else
|
||||
return BigInt::Imp { significand.imp->v / m };
|
||||
}
|
||||
|
||||
BigDecimal BigDecimal::getDecimal() const
|
||||
{
|
||||
if (exp >= 0)
|
||||
return BigDecimal();
|
||||
|
||||
auto m = boost::multiprecision::pow(ten, -exp);
|
||||
|
||||
return BigDecimal(BigInt::Imp { significand.imp->v % m }, exp);
|
||||
}
|
||||
|
||||
|
||||
// ------------------
|
||||
|
||||
|
||||
template<>
|
||||
BigDecimal sqrt(const BigDecimal &v)
|
||||
{
|
||||
// a = sqrt(10^d * v)
|
||||
// a = sqrt(10^d) * sqrt(v)
|
||||
// a = sqrt(10^(d/2)) * sqrt(v)
|
||||
|
||||
auto addedPrecision = 6;
|
||||
auto addedOffset = v.exp % 2 ? 1 : 0;
|
||||
auto offset = addedPrecision + addedOffset;
|
||||
|
||||
auto m = boost::multiprecision::pow(ten, offset);
|
||||
auto vp = BigInt::Imp::V(v.significand.imp->v * m);
|
||||
auto vpr = boost::multiprecision::sqrt(vp);
|
||||
|
||||
auto result = BigDecimal::fromSignificandExponent(
|
||||
BigInt::Imp { std::move(vpr) },
|
||||
(v.exp - offset) / 2
|
||||
);
|
||||
|
||||
/*
|
||||
auto v_ = core::to_string(v);
|
||||
auto vp_ = core::to_string(vp);
|
||||
auto vpr_ = core::to_string(vpr);
|
||||
auto result_ = core::to_string(result);
|
||||
*/
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<>
|
||||
BigDecimal abs(const BigDecimal &v)
|
||||
{
|
||||
return BigDecimal::fromSignificandExponent( abs(v.significand), v.exp );
|
||||
}
|
||||
|
||||
BigDecimal operator*(const BigDecimal &lhs, const BigDecimal &rhs)
|
||||
{
|
||||
// 1.5 = 15, 1
|
||||
// 13 = 13, 0
|
||||
// 19.5 = 195, 1
|
||||
|
||||
return BigDecimal::fromSignificandExponent(lhs.significand * rhs.significand, lhs.exp + rhs.exp);
|
||||
}
|
||||
|
||||
BigDecimal operator/(const BigDecimal &lhs, const BigDecimal &rhs)
|
||||
{
|
||||
static auto precision = 6;
|
||||
static auto m = boost::multiprecision::pow(ten, precision);
|
||||
|
||||
return BigDecimal::fromSignificandExponent(
|
||||
BigInt::Imp{ m * lhs.significand.imp->v / rhs.significand.imp->v },
|
||||
lhs.exp - rhs.exp - precision
|
||||
);
|
||||
}
|
||||
|
||||
BigDecimal operator/(const BigDecimal &lhs, size_t rhs)
|
||||
{
|
||||
return lhs / BigDecimal(rhs);
|
||||
}
|
||||
|
||||
|
||||
BigDecimal operator+(const BigDecimal &lhs, const BigDecimal &rhs)
|
||||
{
|
||||
if (lhs.exp > rhs.exp)
|
||||
return rhs + lhs;
|
||||
|
||||
// 1.5 = 15, 1
|
||||
// 10 = 10, 0
|
||||
|
||||
auto m = boost::multiprecision::pow(ten, rhs.exp - lhs.exp);
|
||||
auto v = m * rhs.significand.imp->v;
|
||||
auto s = v + lhs.significand.imp->v;
|
||||
|
||||
auto result = BigDecimal::fromSignificandExponent(BigInt::Imp { s }, lhs.exp);
|
||||
|
||||
auto lhs_ = core::to_string(lhs);
|
||||
auto rhs_ = core::to_string(rhs);
|
||||
|
||||
auto lhs_s = core::to_string(lhs.significand);
|
||||
auto rhs_s = core::to_string(rhs.significand);
|
||||
|
||||
auto m_ = core::to_string(BigInt(BigInt::Imp { m }));
|
||||
auto v_ = core::to_string(BigInt(BigInt::Imp { v }));
|
||||
auto s_ = core::to_string(BigInt(BigInt::Imp { s }));
|
||||
auto result_ = core::to_string(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
BigDecimal operator-(const BigDecimal &lhs, const BigDecimal &rhs)
|
||||
{
|
||||
return lhs + (-rhs);
|
||||
}
|
||||
|
||||
BigDecimal operator-(const BigDecimal &v)
|
||||
{
|
||||
return BigDecimal::fromSignificandExponent(BigInt::Imp { -v.significand.imp->v }, v.exp);
|
||||
}
|
||||
|
||||
void normalize(BigDecimal &lhs, BigDecimal &rhs)
|
||||
{
|
||||
if (lhs.exp == rhs.exp)
|
||||
return;
|
||||
|
||||
auto *big = (lhs.exp < rhs.exp) ? &rhs : &lhs;
|
||||
auto *small = (lhs.exp < rhs.exp) ? &lhs : &rhs;
|
||||
|
||||
auto d = big->exp - small->exp;
|
||||
auto m = boost::multiprecision::pow(ten, d);
|
||||
|
||||
big->significand.imp->v *= m;
|
||||
big->exp -= d;
|
||||
|
||||
generateDebug(lhs);
|
||||
generateDebug(rhs);
|
||||
}
|
||||
|
||||
|
||||
bool operator==(const BigDecimal &lhs, const BigDecimal &rhs)
|
||||
{
|
||||
// 10 = 1, 1
|
||||
// 10 = 10, 0
|
||||
|
||||
if (lhs.exp == rhs.exp)
|
||||
return lhs.significand == rhs.significand;
|
||||
|
||||
auto lhs_ = lhs;
|
||||
auto rhs_ = rhs;
|
||||
normalize(lhs_, rhs_);
|
||||
|
||||
return (lhs_.significand == rhs_.significand);
|
||||
}
|
||||
|
||||
bool operator<(const BigDecimal &lhs, const BigDecimal &rhs)
|
||||
{
|
||||
if (lhs.exp == rhs.exp)
|
||||
return lhs.significand < rhs.significand;
|
||||
|
||||
auto lhs_ = lhs;
|
||||
auto rhs_ = rhs;
|
||||
normalize(lhs_, rhs_);
|
||||
|
||||
return lhs_.significand < rhs_.significand;
|
||||
}
|
||||
|
||||
bool operator<=(const BigDecimal &lhs, const BigDecimal &rhs)
|
||||
{
|
||||
if (lhs.exp == rhs.exp)
|
||||
return lhs.significand <= rhs.significand;
|
||||
|
||||
auto lhs_ = lhs;
|
||||
auto rhs_ = rhs;
|
||||
normalize(lhs_, rhs_);
|
||||
|
||||
return lhs_.significand <= rhs_.significand;
|
||||
}
|
||||
|
||||
bool operator!=(const BigDecimal &lhs, const BigDecimal &rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
bool operator>(const BigDecimal &lhs, const BigDecimal &rhs)
|
||||
{
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
bool operator>=(const BigDecimal &lhs, const BigDecimal &rhs)
|
||||
{
|
||||
return rhs <= lhs;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
20
tjp/core/math/_delete/BigDecimal.h
Executable file
20
tjp/core/math/_delete/BigDecimal.h
Executable file
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
struct BigDecimal;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
82
tjp/core/math/_delete/BigDecimal.hpp
Executable file
82
tjp/core/math/_delete/BigDecimal.hpp
Executable file
@@ -0,0 +1,82 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BigInt.h"
|
||||
#include "Real.h"
|
||||
|
||||
#define DEBUG_BIGDECIMAL
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
struct BigDecimal {
|
||||
BigInt significand;
|
||||
s32 exp = 0;
|
||||
|
||||
#ifdef DEBUG_BIGDECIMAL
|
||||
std::string debug;
|
||||
#endif
|
||||
|
||||
BigDecimal();
|
||||
explicit BigDecimal(const math::Real &real);
|
||||
explicit BigDecimal(const math::Real &real, s32 precision);
|
||||
|
||||
static BigDecimal fromInteger(BigInt &&integer);
|
||||
static BigDecimal fromIntegerDecimalExponent(const BigInt &integer, const BigInt &decimal, s32 exp=0);
|
||||
static BigDecimal fromReal(math::Real real, s32 precision=16);
|
||||
static BigDecimal fromSignificandExponent(BigInt &&significand, s32 exp);
|
||||
|
||||
BigInt getInteger() const;
|
||||
BigDecimal getDecimal() const;
|
||||
|
||||
static BigDecimal Zero;
|
||||
|
||||
protected:
|
||||
BigDecimal(BigInt &&integer, s32 exp);
|
||||
BigDecimal(const BigInt &integer, const BigInt &decimal, s32 exp);
|
||||
};
|
||||
|
||||
#ifdef DEBUG_BIGDECIMAL
|
||||
void generateDebug(BigDecimal &v);
|
||||
#else
|
||||
inline
|
||||
void generateDebug(BigDecimal &) {}
|
||||
#endif
|
||||
|
||||
template<>
|
||||
BigDecimal sqrt(const BigDecimal &);
|
||||
|
||||
template<>
|
||||
BigDecimal abs(const BigDecimal &);
|
||||
|
||||
BigDecimal operator-(const BigDecimal &lhs);
|
||||
BigDecimal operator-(const BigDecimal &lhs, const BigDecimal &rhs);
|
||||
BigDecimal operator+(const BigDecimal &lhs, const BigDecimal &rhs);
|
||||
BigDecimal operator*(const BigDecimal &lhs, const BigDecimal &rhs);
|
||||
BigDecimal operator/(const BigDecimal &lhs, const BigDecimal &rhs);
|
||||
|
||||
BigDecimal operator/(const BigDecimal &lhs, size_t rhs);
|
||||
|
||||
|
||||
bool operator==(const BigDecimal &lhs, const BigDecimal &rhs);
|
||||
bool operator!=(const BigDecimal &lhs, const BigDecimal &rhs);
|
||||
bool operator<(const BigDecimal &lhs, const BigDecimal &rhs);
|
||||
bool operator<=(const BigDecimal &lhs, const BigDecimal &rhs);
|
||||
bool operator>(const BigDecimal &lhs, const BigDecimal &rhs);
|
||||
bool operator>=(const BigDecimal &lhs, const BigDecimal &rhs);
|
||||
|
||||
void reduce(BigDecimal &);
|
||||
void normalize(BigDecimal &lhs, BigDecimal &rhs);
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
50
tjp/core/math/_delete/BigInt+IO+Test.cpp
Normal file
50
tjp/core/math/_delete/BigInt+IO+Test.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#include "BigInt+IO.h"
|
||||
|
||||
#include <tjp/core/io/bin/IO.h>
|
||||
#include <tjp/core/io/json/in_sajson.h>
|
||||
#include <tjp/core/io/json/out.h>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
namespace test {
|
||||
|
||||
SCENARIO("big int io")
|
||||
{
|
||||
GIVEN("a number")
|
||||
{
|
||||
BigInt a = 10923905823095;
|
||||
|
||||
WHEN("bin")
|
||||
{
|
||||
auto s = io::bin::serialize(a);
|
||||
auto b = io::bin::deserialize<BigInt>(s);
|
||||
|
||||
REQUIRE(a == b);
|
||||
}
|
||||
|
||||
WHEN("json")
|
||||
{
|
||||
auto s = io::json::serialize(a);
|
||||
auto b = io::json::deserialize<BigInt>(s);
|
||||
|
||||
REQUIRE(a == b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
41
tjp/core/math/_delete/BigInt+IO.cpp
Normal file
41
tjp/core/math/_delete/BigInt+IO.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
//
|
||||
// MathIO.h
|
||||
// common
|
||||
//
|
||||
// Created by Timothy Prepscius on 8/4/18.
|
||||
// Copyright © 2018 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#include "BigInt+IO.h"
|
||||
#include "BigInt+Imp.hpp"
|
||||
#include <tjp/core/assert/debug_assert.h>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
void write(const BigInt &v, Vector<char> &bytes)
|
||||
{
|
||||
auto *mp = &v.imp->v.backend().data();
|
||||
auto binSize = mp_ubin_size(mp);
|
||||
|
||||
bytes.resize(binSize);
|
||||
|
||||
size_t written;
|
||||
auto error = mp_to_ubin(mp, (unsigned char *)bytes.data(), bytes.size(), &written);
|
||||
debug_assert(written == binSize);
|
||||
debug_assert(error == 0);
|
||||
}
|
||||
|
||||
void read(BigInt &v, const Vector<char> &bytes)
|
||||
{
|
||||
auto *mp = &v.imp->v.backend().data();
|
||||
|
||||
auto error = mp_from_ubin(mp, (unsigned char *)bytes.data(), bytes.size());
|
||||
debug_assert(error == 0);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
54
tjp/core/math/_delete/BigInt+IO.h
Normal file
54
tjp/core/math/_delete/BigInt+IO.h
Normal file
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// MathIO.h
|
||||
// common
|
||||
//
|
||||
// Created by Timothy Prepscius on 8/4/18.
|
||||
// Copyright © 2018 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BigInt.h"
|
||||
|
||||
#include <tjp/core/containers/Vector.h>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
|
||||
void write(const BigInt &v, Vector<char> &bytes);
|
||||
void read(BigInt &, const Vector<char> &bytes);
|
||||
|
||||
template<typename IO>
|
||||
void io_w(IO &io, const tjp::core::math::BigInt &v)
|
||||
{
|
||||
std::vector<char> bytes;
|
||||
write(v, bytes);
|
||||
io.any(bytes);
|
||||
}
|
||||
|
||||
template<typename IO>
|
||||
void io_r(IO &io, tjp::core::math::BigInt &v)
|
||||
{
|
||||
std::vector<char> bytes;
|
||||
io.any(bytes);
|
||||
read(v, bytes);
|
||||
}
|
||||
|
||||
template<typename IO>
|
||||
void io_bin_w(IO &io, const tjp::core::math::BigInt &v) { return io_w(io, v); }
|
||||
|
||||
template<typename IO>
|
||||
void io_json_w(IO &io, const tjp::core::math::BigInt &v) { return io_w(io, v); }
|
||||
|
||||
template<typename IO>
|
||||
void io_bin_r(IO &io, tjp::core::math::BigInt &v) { return io_r(io, v); }
|
||||
|
||||
template<typename IO>
|
||||
void io_json_r(IO &io, tjp::core::math::BigInt &v) { return io_r(io, v); }
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
29
tjp/core/math/_delete/BigInt+Imp.hpp
Executable file
29
tjp/core/math/_delete/BigInt+Imp.hpp
Executable file
@@ -0,0 +1,29 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tjp/core/system/DisableWarningsPush.h>
|
||||
#include <boost/multiprecision/tommath.hpp>
|
||||
#include <tjp/core/system/DisableWarningsPop.h>
|
||||
|
||||
#include "Real.h"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
struct BigInt::Imp {
|
||||
typedef boost::multiprecision::tom_int V;
|
||||
V v;
|
||||
} ;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
63
tjp/core/math/_delete/BigInt+Test.cpp
Executable file
63
tjp/core/math/_delete/BigInt+Test.cpp
Executable file
@@ -0,0 +1,63 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#include "BigInt.h"
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
namespace test {
|
||||
|
||||
SCENARIO("big int")
|
||||
{
|
||||
GIVEN("a number")
|
||||
{
|
||||
BigInt a = 1;
|
||||
|
||||
WHEN("add")
|
||||
{
|
||||
a += 2;
|
||||
|
||||
REQUIRE(a == 3);
|
||||
}
|
||||
|
||||
WHEN("sqrt")
|
||||
{
|
||||
a = 17;
|
||||
auto b = sqrt(a);
|
||||
|
||||
REQUIRE(b == 4);
|
||||
}
|
||||
|
||||
WHEN("and")
|
||||
{
|
||||
a = 32767;
|
||||
auto b = a & 0xFF;
|
||||
|
||||
REQUIRE(b == 0xFF);
|
||||
}
|
||||
|
||||
WHEN("shift")
|
||||
{
|
||||
a = 0xDEDEFEFE;
|
||||
auto b = a >> 16;
|
||||
|
||||
REQUIRE(b == 0xDEDE);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
235
tjp/core/math/_delete/BigInt.cpp
Executable file
235
tjp/core/math/_delete/BigInt.cpp
Executable file
@@ -0,0 +1,235 @@
|
||||
//
|
||||
// Math.cpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#include "BigInt.hpp"
|
||||
#include "BigInt+Imp.hpp"
|
||||
|
||||
#include <tjp/core/algorithm/remove_const_of_var.hpp>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
BigInt BigInt::Zero(0);
|
||||
|
||||
BigInt::Imp::V &m(BigInt &v)
|
||||
{
|
||||
return v.imp->v;
|
||||
}
|
||||
|
||||
const BigInt::Imp::V &m(const BigInt &v)
|
||||
{
|
||||
return v.imp->v;
|
||||
}
|
||||
|
||||
BigInt::Imp::V &c(BigInt &v)
|
||||
{
|
||||
if (v.imp == nullptr)
|
||||
v.imp = core::strong<BigInt::Imp>();
|
||||
|
||||
return m(v);
|
||||
}
|
||||
|
||||
|
||||
BigInt::Imp::V &c(const BigInt &v)
|
||||
{
|
||||
return c(remove_const_of_var(v));
|
||||
}
|
||||
|
||||
|
||||
BigInt::BigInt()
|
||||
{
|
||||
c(*this);
|
||||
}
|
||||
|
||||
BigInt::BigInt(s64 v)
|
||||
{
|
||||
c(*this) = v;
|
||||
}
|
||||
|
||||
BigInt::BigInt(Imp &&imp_) :
|
||||
imp(core::strong<BigInt::Imp>(std::move(imp_)))
|
||||
{
|
||||
}
|
||||
|
||||
BigInt::BigInt(const StringView &s)
|
||||
{
|
||||
c(*this) = Imp::V(s);
|
||||
}
|
||||
|
||||
BigInt::BigInt(const BigInt &v)
|
||||
{
|
||||
c(*this) = m(v);
|
||||
}
|
||||
|
||||
s64 BigInt::toInteger() const
|
||||
{
|
||||
return c(*this).convert_to<s64>();
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<>
|
||||
BigInt sqrt(const BigInt &b)
|
||||
{
|
||||
BigInt result;
|
||||
c(result) = boost::multiprecision::sqrt(m(b));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<>
|
||||
BigInt abs(const BigInt &b)
|
||||
{
|
||||
BigInt result;
|
||||
c(result) = boost::multiprecision::abs(m(b));
|
||||
return result;
|
||||
}
|
||||
|
||||
template<>
|
||||
BigInt pow2(const BigInt &b)
|
||||
{
|
||||
BigInt result;
|
||||
c(result) = m(b) * m(b);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool is_zero(const BigInt &lhs)
|
||||
{
|
||||
return m(lhs).is_zero();
|
||||
}
|
||||
|
||||
BigInt operator %(const BigInt &lhs, int rhs)
|
||||
{
|
||||
BigInt r;
|
||||
c(r) = m(lhs) % rhs;
|
||||
return r;
|
||||
}
|
||||
|
||||
BigInt operator %(const BigInt &lhs, const BigInt &rhs)
|
||||
{
|
||||
BigInt r;
|
||||
c(r) = m(lhs) % m(rhs);
|
||||
return r;
|
||||
}
|
||||
|
||||
BigInt operator /(const BigInt &lhs, int rhs)
|
||||
{
|
||||
BigInt r;
|
||||
c(r) = m(lhs) / rhs;
|
||||
return r;
|
||||
}
|
||||
|
||||
BigInt operator /(const BigInt &lhs, size_t rhs)
|
||||
{
|
||||
BigInt r;
|
||||
c(r) = m(lhs) / rhs;
|
||||
return r;
|
||||
}
|
||||
|
||||
BigInt &operator /=(BigInt &lhs, int rhs)
|
||||
{
|
||||
m(lhs) = m(lhs) / rhs;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
BigInt operator *(int lhs, const BigInt &rhs)
|
||||
{
|
||||
BigInt r;
|
||||
c(r) = lhs * m(rhs);
|
||||
return r;
|
||||
}
|
||||
|
||||
BigInt operator *(const BigInt &rhs, int lhs)
|
||||
{
|
||||
return lhs * rhs;
|
||||
}
|
||||
|
||||
BigInt operator +(const BigInt &lhs, const BigInt &rhs)
|
||||
{
|
||||
BigInt r;
|
||||
c(r) = m(lhs) + m(rhs);
|
||||
return r;
|
||||
}
|
||||
|
||||
BigInt operator -(const BigInt &lhs, const BigInt &rhs)
|
||||
{
|
||||
BigInt r;
|
||||
c(r) = m(lhs) - m(rhs);
|
||||
return r;
|
||||
}
|
||||
|
||||
BigInt operator *(const BigInt &lhs, const BigInt &rhs)
|
||||
{
|
||||
BigInt r;
|
||||
c(r) = m(lhs) * m(rhs);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
BigInt operator /(const BigInt &lhs, const BigInt &rhs)
|
||||
{
|
||||
BigInt r;
|
||||
c(r) = m(lhs) / m(rhs);
|
||||
return r;
|
||||
}
|
||||
|
||||
math::Real toReal(const BigInt &lhs)
|
||||
{
|
||||
return m(lhs).convert_to<math::Real>();
|
||||
}
|
||||
|
||||
bool operator ==(const BigInt &lhs, const BigInt &rhs)
|
||||
{
|
||||
return m(lhs) == m(rhs);
|
||||
}
|
||||
|
||||
bool operator <(const BigInt &lhs, const BigInt &rhs)
|
||||
{
|
||||
return m(lhs) < m(rhs);
|
||||
}
|
||||
|
||||
bool operator <=(const BigInt &lhs, const BigInt &rhs)
|
||||
{
|
||||
return m(lhs) <= m(rhs);
|
||||
}
|
||||
|
||||
bool operator >(const BigInt &lhs, const BigInt &rhs)
|
||||
{
|
||||
return m(lhs) > m(rhs);
|
||||
}
|
||||
|
||||
bool operator >=(const BigInt &lhs, const BigInt &rhs)
|
||||
{
|
||||
return m(lhs) >= m(rhs);
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &o, const math::BigInt &v)
|
||||
{
|
||||
return o << m(v);
|
||||
}
|
||||
|
||||
BigInt distance_squared(const BigInt &lhs, const BigInt &rhs)
|
||||
{
|
||||
return pow2(rhs-lhs);
|
||||
}
|
||||
|
||||
BigInt distance_relative(const BigInt &lhs, const BigInt &rhs)
|
||||
{
|
||||
return distance(lhs,rhs);
|
||||
}
|
||||
|
||||
BigInt distance(const BigInt &lhs, const BigInt &rhs)
|
||||
{
|
||||
return rhs > lhs ? (rhs-lhs) : (lhs-rhs);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
81
tjp/core/math/_delete/BigInt.h
Executable file
81
tjp/core/math/_delete/BigInt.h
Executable file
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Real.h"
|
||||
#include <tjp/core/ptr/Ptr.hpp>
|
||||
#include <tjp/core/string/String.h>
|
||||
#include <tjp/core/string/StringView.h>
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
|
||||
struct BigInt {
|
||||
struct Imp;
|
||||
core::StrongPtr<Imp> imp;
|
||||
|
||||
explicit BigInt(const StringView &v);
|
||||
explicit BigInt(s64 i);
|
||||
|
||||
BigInt(Imp &&imp);
|
||||
BigInt();
|
||||
BigInt(const BigInt &m);
|
||||
|
||||
static BigInt Zero;
|
||||
|
||||
s64 toInteger() const;
|
||||
};
|
||||
|
||||
template<>
|
||||
BigInt sqrt(const BigInt &);
|
||||
|
||||
template<>
|
||||
BigInt abs(const BigInt &);
|
||||
|
||||
bool is_zero(const BigInt &lhs);
|
||||
BigInt operator %(const BigInt &lhs, int rhs);
|
||||
BigInt operator %(const BigInt &lhs, const BigInt &rhs);
|
||||
BigInt operator /(const BigInt &lhs, int rhs);
|
||||
BigInt operator *(const BigInt &lhs, int rhs);
|
||||
BigInt &operator /=(BigInt &lhs, int rhs);
|
||||
|
||||
BigInt operator /(const BigInt &lhs, size_t rhs);
|
||||
|
||||
|
||||
BigInt operator *(int lhs, const BigInt &rhs);
|
||||
BigInt operator +(const BigInt &lhs, const BigInt &rhs);
|
||||
BigInt operator -(const BigInt &lhs, const BigInt &rhs);
|
||||
BigInt operator *(const BigInt &lhs, const BigInt &rhs);
|
||||
BigInt operator /(const BigInt &lhs, const BigInt &rhs);
|
||||
|
||||
math::Real toReal(const BigInt &lhs);
|
||||
|
||||
bool operator ==(const BigInt &lhs, const BigInt &rhs);
|
||||
bool operator <(const BigInt &lhs, const BigInt &rhs);
|
||||
bool operator <=(const BigInt &lhs, const BigInt &rhs);
|
||||
|
||||
bool operator >(const BigInt &lhs, const BigInt &rhs);
|
||||
bool operator >=(const BigInt &lhs, const BigInt &rhs);
|
||||
|
||||
std::ostream &operator<<(std::ostream &o, const math::BigInt &v);
|
||||
|
||||
BigInt distance_squared(const BigInt &lhs, const BigInt &rhs);
|
||||
BigInt distance_relative(const BigInt &lhs, const BigInt &rhs);
|
||||
BigInt distance(const BigInt &lhs, const BigInt &rhs);
|
||||
|
||||
} // namespace
|
||||
|
||||
//std::string to_string(const math::BigInt &t);
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
11
tjp/core/math/_delete/BigInt.hpp
Executable file
11
tjp/core/math/_delete/BigInt.hpp
Executable file
@@ -0,0 +1,11 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BigInt.h"
|
||||
79
tjp/core/math/_tests/Algorithm+Segment.cpp
Executable file
79
tjp/core/math/_tests/Algorithm+Segment.cpp
Executable file
@@ -0,0 +1,79 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#include <tjp/core/math/Algorithm+Segment.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace math {
|
||||
namespace test {
|
||||
|
||||
SCENARIO("math_segment")
|
||||
{
|
||||
GIVEN("a segment")
|
||||
{
|
||||
Segment1<int> a = { 10, 15 };
|
||||
|
||||
Segment1<int> b = {4,9};
|
||||
REQUIRE(!intersects(b, a));
|
||||
REQUIRE(!intersects(a, b));
|
||||
REQUIRE(!contains(b, a));
|
||||
REQUIRE(!contains(a, b));
|
||||
REQUIRE(intersects(b, a, 1));
|
||||
REQUIRE(intersects(a, b, 1));
|
||||
|
||||
Segment1<int> c = {9,11};
|
||||
REQUIRE(intersects(c, a));
|
||||
REQUIRE(intersects(a, c));
|
||||
REQUIRE(!contains(c, a));
|
||||
REQUIRE(!contains(a, c));
|
||||
REQUIRE(intersects(c, a, 1));
|
||||
REQUIRE(intersects(a, c, 1));
|
||||
|
||||
|
||||
Segment1<int> d = {11,11};
|
||||
REQUIRE(intersects(d, a));
|
||||
REQUIRE(intersects(a, d));
|
||||
REQUIRE(!contains(d, a));
|
||||
REQUIRE(contains(a, d));
|
||||
REQUIRE(intersects(d, a, 1));
|
||||
REQUIRE(intersects(a, d, 1));
|
||||
|
||||
Segment1<int> e = {11,12};
|
||||
REQUIRE(intersects(e, a));
|
||||
REQUIRE(intersects(a, e));
|
||||
REQUIRE(!contains(e, a));
|
||||
REQUIRE(contains(a, e));
|
||||
|
||||
Segment1<int> f = {12,16};
|
||||
REQUIRE(intersects(f, a));
|
||||
REQUIRE(intersects(a, f));
|
||||
|
||||
Segment1<int> g = {16,19};
|
||||
REQUIRE(!intersects(g, a));
|
||||
REQUIRE(!intersects(a, g));
|
||||
REQUIRE(intersects(g, a, 1));
|
||||
REQUIRE(intersects(a, g, 1));
|
||||
|
||||
Segment1<int> h = {4,19};
|
||||
REQUIRE(intersects(h, a));
|
||||
REQUIRE(intersects(a, h));
|
||||
REQUIRE(contains(h, a));
|
||||
REQUIRE(!contains(a, h));
|
||||
REQUIRE(intersects(h, a, 1));
|
||||
REQUIRE(intersects(a, h, 1));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
19
tjp/core/math/_tests/Algorithm.cpp
Executable file
19
tjp/core/math/_tests/Algorithm.cpp
Executable file
@@ -0,0 +1,19 @@
|
||||
//
|
||||
// Math.cpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#include <tjp/core/math/Algorithm.hpp>
|
||||
#include <vector>
|
||||
#include <tjp/core/math/Vector2.inl>
|
||||
|
||||
using namespace tjp::core::math;
|
||||
|
||||
void test_math_algorithm ()
|
||||
{
|
||||
Vector2f a, b;
|
||||
auto c = mul(a, b);
|
||||
}
|
||||
133
tjp/core/math/_tests/FloatPack.cpp
Executable file
133
tjp/core/math/_tests/FloatPack.cpp
Executable file
@@ -0,0 +1,133 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#include <tjp/core/math/FloatPack.inl>
|
||||
#include <tjp/core/math/Distance.inl>
|
||||
|
||||
#include <tjp/core/random/Random.h>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
|
||||
namespace tjp::core::math {
|
||||
namespace {
|
||||
|
||||
const auto precision = 0.0000000000000000001;
|
||||
|
||||
//template<typename R>
|
||||
//bool close(R l, R r)
|
||||
//{
|
||||
// return std::abs(r - l) < precision;
|
||||
//}
|
||||
|
||||
|
||||
bool close(Vector4f l, Vector4f r, r32 p)
|
||||
{
|
||||
for (auto i=0; i<4; ++i)
|
||||
if (std::abs(l[i] - r[i]) > p)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool close(Vector3f l, Vector3f r, r32 p)
|
||||
{
|
||||
for (auto i=0; i<3; ++i)
|
||||
if (std::abs(l[i] - r[i]) > p)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool close(Vector2f l, Vector2f r, r32 p)
|
||||
{
|
||||
for (auto i=0; i<2; ++i)
|
||||
if (std::abs(l[i] - r[i]) > p)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
SCENARIO("floatpack")
|
||||
{
|
||||
// GIVEN("a number")
|
||||
// {
|
||||
// //0.0000000000000000001
|
||||
// float a = 0.2412541239199123125;
|
||||
//
|
||||
// WHEN("enc-dec-vec4")
|
||||
// {
|
||||
// auto v = toVec4f(a);
|
||||
// auto a_ = toFloat(v);
|
||||
//
|
||||
// REQUIRE(close(a, a_));
|
||||
// }
|
||||
//
|
||||
// WHEN("enc-dec-vec2")
|
||||
// {
|
||||
// auto v = toVec2f(a);
|
||||
// auto a_ = toFloat(v);
|
||||
//
|
||||
// REQUIRE(close(a, a_));
|
||||
// }
|
||||
//
|
||||
// WHEN("enc-dec-vec3")
|
||||
// {
|
||||
// auto v = toVec3f(a);
|
||||
// auto a_ = toFloat(v);
|
||||
//
|
||||
// REQUIRE(close(a, a_));
|
||||
// }
|
||||
// }
|
||||
|
||||
GIVEN("a vector")
|
||||
{
|
||||
for (auto i=0; i<10000; ++i)
|
||||
{
|
||||
auto a = StandardRandom.nextReal<float>();
|
||||
auto b = StandardRandom.nextReal<float>();
|
||||
auto c = StandardRandom.nextReal<float>();
|
||||
auto d = StandardRandom.nextReal<float>();
|
||||
|
||||
// WHEN("vec4")
|
||||
{
|
||||
Vector4f v { a, b, c, d };
|
||||
auto a_ = pack4u(v);
|
||||
auto v_ = unpack4u(a_);
|
||||
|
||||
bool isClose = close(v, v_, 1/float_4_max);
|
||||
REQUIRE(isClose);
|
||||
}
|
||||
|
||||
// WHEN("vec3")
|
||||
{
|
||||
Vector3f v { a, b, c };
|
||||
auto a_ = pack3u(v);
|
||||
auto v_ = unpack3u(a_);
|
||||
|
||||
bool isClose = close(v, v_, 1/float_3_max);
|
||||
|
||||
REQUIRE(isClose);
|
||||
}
|
||||
|
||||
// WHEN("vec2")
|
||||
{
|
||||
Vector2f v { a, b };
|
||||
auto a_ = pack2u(v);
|
||||
auto v_ = unpack2u(a_);
|
||||
|
||||
bool isClose = close(v, v_, 1/float_2_max);
|
||||
|
||||
REQUIRE(isClose);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
24
tjp/core/math/clamp.hpp
Executable file
24
tjp/core/math/clamp.hpp
Executable file
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp::core::math {
|
||||
|
||||
template<typename V, typename L, typename R>
|
||||
inline V clamp(const V &v, const L &l, const R &r)
|
||||
{
|
||||
if (v < l)
|
||||
return (V)l;
|
||||
if (v > r)
|
||||
return (V)r;
|
||||
return v;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
692
tjp/core/math/detail/Wm5.cpp
Normal file
692
tjp/core/math/detail/Wm5.cpp
Normal file
@@ -0,0 +1,692 @@
|
||||
//
|
||||
// Wm5.cpp
|
||||
// algorithm
|
||||
//
|
||||
// Created by Timothy Prepscius on 5/3/18.
|
||||
// Copyright © 2018 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#include "Wm5.h"
|
||||
|
||||
#define assertion(...)
|
||||
|
||||
namespace Wm5 {
|
||||
|
||||
template<> const float Math<float>::ZERO_TOLERANCE = 1e-06f;
|
||||
|
||||
template<> const double Math<double>::ZERO_TOLERANCE = 1e-08;
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template <typename Real>
|
||||
EigenDecomposition<Real>::EigenDecomposition (int size)
|
||||
:
|
||||
mMatrix(size, size)
|
||||
{
|
||||
assertion(size >= 2, "Invalid size in Eigendecomposition constructor\n");
|
||||
|
||||
mSize = size;
|
||||
mDiagonal = new1<Real>(mSize);
|
||||
mSubdiagonal = new1<Real>(mSize);
|
||||
mIsRotation = false;
|
||||
}
|
||||
/*
|
||||
//----------------------------------------------------------------------------
|
||||
template <typename Real>
|
||||
EigenDecomposition<Real>::EigenDecomposition (const Matrix2<Real>& mat)
|
||||
:
|
||||
mMatrix(2, 2, &mat[0][0])
|
||||
{
|
||||
mSize = 2;
|
||||
mDiagonal = new1<Real>(mSize);
|
||||
mSubdiagonal = new1<Real>(mSize);
|
||||
mIsRotation = false;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
template <typename Real>
|
||||
EigenDecomposition<Real>::EigenDecomposition (const Matrix3<Real>& mat)
|
||||
:
|
||||
mMatrix(3, 3, &mat[0][0])
|
||||
{
|
||||
mSize = 3;
|
||||
mDiagonal = new1<Real>(mSize);
|
||||
mSubdiagonal = new1<Real>(mSize);
|
||||
mIsRotation = false;
|
||||
}
|
||||
*/
|
||||
//----------------------------------------------------------------------------
|
||||
template <typename Real>
|
||||
EigenDecomposition<Real>::EigenDecomposition (const GMatrix<Real>& mat)
|
||||
:
|
||||
mMatrix(mat)
|
||||
{
|
||||
mSize = mat.GetRows();
|
||||
assertion(mSize >= 2 && (mat.GetColumns() == mSize),
|
||||
"Square matrix required in EigenDecomposition constructor\n");
|
||||
|
||||
mDiagonal = new1<Real>(mSize);
|
||||
mSubdiagonal = new1<Real>(mSize);
|
||||
mIsRotation = false;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
template <typename Real>
|
||||
EigenDecomposition<Real>::~EigenDecomposition ()
|
||||
{
|
||||
delete1(mDiagonal);
|
||||
delete1(mSubdiagonal);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
template <typename Real>
|
||||
Real& EigenDecomposition<Real>::operator() (int row, int column)
|
||||
{
|
||||
return mMatrix[row][column];
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/*
|
||||
template <typename Real>
|
||||
EigenDecomposition<Real>& EigenDecomposition<Real>::operator= (
|
||||
const Matrix2<Real>& mat)
|
||||
{
|
||||
mMatrix.SetMatrix(2, 2, &mat[0][0]);
|
||||
mSize = 2;
|
||||
delete1(mDiagonal);
|
||||
delete1(mSubdiagonal);
|
||||
mDiagonal = new1<Real>(mSize);
|
||||
mSubdiagonal = new1<Real>(mSize);
|
||||
return *this;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
template <typename Real>
|
||||
EigenDecomposition<Real>& EigenDecomposition<Real>::operator= (
|
||||
const Matrix3<Real>& mat)
|
||||
{
|
||||
mMatrix.SetMatrix(3, 3, &mat[0][0]);
|
||||
mSize = 3;
|
||||
delete1(mDiagonal);
|
||||
delete1(mSubdiagonal);
|
||||
mDiagonal = new1<Real>(mSize);
|
||||
mSubdiagonal = new1<Real>(mSize);
|
||||
return *this;
|
||||
}
|
||||
*/
|
||||
//----------------------------------------------------------------------------
|
||||
template <typename Real>
|
||||
EigenDecomposition<Real>& EigenDecomposition<Real>::operator= (
|
||||
const GMatrix<Real>& mat)
|
||||
{
|
||||
mMatrix = mat;
|
||||
return *this;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
template <typename Real>
|
||||
void EigenDecomposition<Real>::Solve (bool increasingSort)
|
||||
{
|
||||
if (mSize == 2)
|
||||
{
|
||||
Tridiagonal2();
|
||||
}
|
||||
else if (mSize == 3)
|
||||
{
|
||||
Tridiagonal3();
|
||||
}
|
||||
else
|
||||
{
|
||||
TridiagonalN();
|
||||
}
|
||||
|
||||
QLAlgorithm();
|
||||
|
||||
if (increasingSort)
|
||||
{
|
||||
IncreasingSort();
|
||||
}
|
||||
else
|
||||
{
|
||||
DecreasingSort();
|
||||
}
|
||||
|
||||
GuaranteeRotation();
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
template <typename Real>
|
||||
Real EigenDecomposition<Real>::GetEigenvalue (int i) const
|
||||
{
|
||||
assertion(0 <= i && i < mSize, "Invalid index in GetEigenvalue\n");
|
||||
return mDiagonal[i];
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
template <typename Real>
|
||||
const Real* EigenDecomposition<Real>::GetEigenvalues () const
|
||||
{
|
||||
return mDiagonal;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/*
|
||||
template <typename Real>
|
||||
Vector2<Real> EigenDecomposition<Real>::GetEigenvector2 (int i) const
|
||||
{
|
||||
assertion(mSize == 2, "Mismatched dimension in GetEigenvector2\n");
|
||||
|
||||
if (mSize == 2)
|
||||
{
|
||||
Vector2<Real> eigenvector;
|
||||
for (int row = 0; row < mSize; ++row)
|
||||
{
|
||||
eigenvector[row] = mMatrix[row][i];
|
||||
}
|
||||
return eigenvector;
|
||||
}
|
||||
return Vector2<Real>::ZERO;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
template <typename Real>
|
||||
Matrix2<Real> EigenDecomposition<Real>::GetEigenvectors2 () const
|
||||
{
|
||||
assertion(mSize == 2, "Mismatched dimension in GetEigenvectors2\n");
|
||||
|
||||
Matrix2<Real> eigenvectors;
|
||||
for (int row = 0; row < 2; ++row)
|
||||
{
|
||||
for (int column = 0; column < 2; ++column)
|
||||
{
|
||||
eigenvectors[row][column] = mMatrix[row][column];
|
||||
}
|
||||
}
|
||||
return eigenvectors;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
template <typename Real>
|
||||
Vector3<Real> EigenDecomposition<Real>::GetEigenvector3 (int i) const
|
||||
{
|
||||
assertion(mSize == 3, "Mismatched dimension in GetEigenvector3\n");
|
||||
|
||||
if (mSize == 3)
|
||||
{
|
||||
Vector3<Real> eigenvector;
|
||||
for (int row = 0; row < mSize; ++row)
|
||||
{
|
||||
eigenvector[row] = mMatrix[row][i];
|
||||
}
|
||||
return eigenvector;
|
||||
}
|
||||
return Vector3<Real>::ZERO;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
template <typename Real>
|
||||
Matrix3<Real> EigenDecomposition<Real>::GetEigenvectors3 () const
|
||||
{
|
||||
assertion(mSize == 3, "Mismatched dimension in GetEigenvectors2\n");
|
||||
|
||||
Matrix3<Real> eigenvectors;
|
||||
for (int row = 0; row < 3; ++row)
|
||||
{
|
||||
for (int column = 0; column < 3; ++column)
|
||||
{
|
||||
eigenvectors[row][column] = mMatrix[row][column];
|
||||
}
|
||||
}
|
||||
return eigenvectors;
|
||||
}
|
||||
*/
|
||||
//----------------------------------------------------------------------------
|
||||
template <typename Real>
|
||||
GVector<Real> EigenDecomposition<Real>::GetEigenvector (int i) const
|
||||
{
|
||||
return mMatrix.GetColumn(i);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
template <typename Real>
|
||||
const GMatrix<Real>& EigenDecomposition<Real>::GetEigenvectors () const
|
||||
{
|
||||
return mMatrix;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
template <typename Real>
|
||||
void EigenDecomposition<Real>::Tridiagonal2 ()
|
||||
{
|
||||
// The matrix is already tridiagonal.
|
||||
mDiagonal[0] = mMatrix[0][0];
|
||||
mDiagonal[1] = mMatrix[1][1];
|
||||
mSubdiagonal[0] = mMatrix[0][1];
|
||||
mSubdiagonal[1] = (Real)0;
|
||||
mMatrix[0][0] = (Real)1;
|
||||
mMatrix[0][1] = (Real)0;
|
||||
mMatrix[1][0] = (Real)0;
|
||||
mMatrix[1][1] = (Real)1;
|
||||
|
||||
mIsRotation = true;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
template <typename Real>
|
||||
void EigenDecomposition<Real>::Tridiagonal3 ()
|
||||
{
|
||||
Real m00 = mMatrix[0][0];
|
||||
Real m01 = mMatrix[0][1];
|
||||
Real m02 = mMatrix[0][2];
|
||||
Real m11 = mMatrix[1][1];
|
||||
Real m12 = mMatrix[1][2];
|
||||
Real m22 = mMatrix[2][2];
|
||||
|
||||
mDiagonal[0] = m00;
|
||||
mSubdiagonal[2] = (Real)0;
|
||||
if (Math<Real>::FAbs(m02) > Math<Real>::ZERO_TOLERANCE)
|
||||
{
|
||||
Real length = Math<Real>::Sqrt(m01*m01 + m02*m02);
|
||||
Real invLength = ((Real)1)/length;
|
||||
m01 *= invLength;
|
||||
m02 *= invLength;
|
||||
Real q = ((Real)2)*m01*m12 + m02*(m22 - m11);
|
||||
mDiagonal[1] = m11 + m02*q;
|
||||
mDiagonal[2] = m22 - m02*q;
|
||||
mSubdiagonal[0] = length;
|
||||
mSubdiagonal[1] = m12 - m01*q;
|
||||
mMatrix[0][0] = (Real)1;
|
||||
mMatrix[0][1] = (Real)0;
|
||||
mMatrix[0][2] = (Real)0;
|
||||
mMatrix[1][0] = (Real)0;
|
||||
mMatrix[1][1] = m01;
|
||||
mMatrix[1][2] = m02;
|
||||
mMatrix[2][0] = (Real)0;
|
||||
mMatrix[2][1] = m02;
|
||||
mMatrix[2][2] = -m01;
|
||||
mIsRotation = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
mDiagonal[1] = m11;
|
||||
mDiagonal[2] = m22;
|
||||
mSubdiagonal[0] = m01;
|
||||
mSubdiagonal[1] = m12;
|
||||
mMatrix[0][0] = (Real)1;
|
||||
mMatrix[0][1] = (Real)0;
|
||||
mMatrix[0][2] = (Real)0;
|
||||
mMatrix[1][0] = (Real)0;
|
||||
mMatrix[1][1] = (Real)1;
|
||||
mMatrix[1][2] = (Real)0;
|
||||
mMatrix[2][0] = (Real)0;
|
||||
mMatrix[2][1] = (Real)0;
|
||||
mMatrix[2][2] = (Real)1;
|
||||
mIsRotation = true;
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
template <typename Real>
|
||||
void EigenDecomposition<Real>::TridiagonalN ()
|
||||
{
|
||||
// TODO: This is Numerical Recipes in C code. Rewrite to avoid
|
||||
// copyright issues.
|
||||
|
||||
int i0, i1, i2, i3;
|
||||
|
||||
for (i0 = mSize - 1, i3 = mSize - 2; i0 >= 1; --i0, --i3)
|
||||
{
|
||||
Real value0 = (Real)0;
|
||||
Real scale = (Real)0;
|
||||
|
||||
if (i3 > 0)
|
||||
{
|
||||
for (i2 = 0; i2 <= i3; ++i2)
|
||||
{
|
||||
scale += Math<Real>::FAbs(mMatrix[i0][i2]);
|
||||
}
|
||||
if (scale == (Real)0)
|
||||
{
|
||||
mSubdiagonal[i0] = mMatrix[i0][i3];
|
||||
}
|
||||
else
|
||||
{
|
||||
Real invScale = ((Real)1)/scale;
|
||||
for (i2 = 0; i2 <= i3; ++i2)
|
||||
{
|
||||
mMatrix[i0][i2] *= invScale;
|
||||
value0 += mMatrix[i0][i2]*mMatrix[i0][i2];
|
||||
}
|
||||
|
||||
Real value1 = mMatrix[i0][i3];
|
||||
Real value2 = Math<Real>::Sqrt(value0);
|
||||
if (value1 > (Real)0)
|
||||
{
|
||||
value2 = -value2;
|
||||
}
|
||||
|
||||
mSubdiagonal[i0] = scale*value2;
|
||||
value0 -= value1*value2;
|
||||
mMatrix[i0][i3] = value1-value2;
|
||||
value1 = (Real)0;
|
||||
Real invValue0 = ((Real)1)/value0;
|
||||
for (i1 = 0; i1 <= i3; ++i1)
|
||||
{
|
||||
mMatrix[i1][i0] = mMatrix[i0][i1]*invValue0;
|
||||
value2 = (Real)0;
|
||||
for (i2 = 0; i2 <= i1; ++i2)
|
||||
{
|
||||
value2 += mMatrix[i1][i2]*mMatrix[i0][i2];
|
||||
}
|
||||
for (i2 = i1+1; i2 <= i3; ++i2)
|
||||
{
|
||||
value2 += mMatrix[i2][i1]*mMatrix[i0][i2];
|
||||
}
|
||||
mSubdiagonal[i1] = value2*invValue0;
|
||||
value1 += mSubdiagonal[i1]*mMatrix[i0][i1];
|
||||
}
|
||||
|
||||
Real value3 = ((Real)0.5)*value1*invValue0;
|
||||
for (i1 = 0; i1 <= i3; ++i1)
|
||||
{
|
||||
value1 = mMatrix[i0][i1];
|
||||
value2 = mSubdiagonal[i1] - value3*value1;
|
||||
mSubdiagonal[i1] = value2;
|
||||
for (i2 = 0; i2 <= i1; i2++)
|
||||
{
|
||||
mMatrix[i1][i2] -=
|
||||
value1*mSubdiagonal[i2] + value2*mMatrix[i0][i2];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mSubdiagonal[i0] = mMatrix[i0][i3];
|
||||
}
|
||||
|
||||
mDiagonal[i0] = value0;
|
||||
}
|
||||
|
||||
mDiagonal[0] = (Real)0;
|
||||
mSubdiagonal[0] = (Real)0;
|
||||
for (i0 = 0, i3 = -1; i0 <= mSize - 1; ++i0, ++i3)
|
||||
{
|
||||
if (mDiagonal[i0] != (Real)0)
|
||||
{
|
||||
for (i1 = 0; i1 <= i3; ++i1)
|
||||
{
|
||||
Real sum = (Real)0;
|
||||
for (i2 = 0; i2 <= i3; ++i2)
|
||||
{
|
||||
sum += mMatrix[i0][i2]*mMatrix[i2][i1];
|
||||
}
|
||||
for (i2 = 0; i2 <= i3; ++i2)
|
||||
{
|
||||
mMatrix[i2][i1] -= sum*mMatrix[i2][i0];
|
||||
}
|
||||
}
|
||||
}
|
||||
mDiagonal[i0] = mMatrix[i0][i0];
|
||||
mMatrix[i0][i0] = (Real)1;
|
||||
for (i1 = 0; i1 <= i3; ++i1)
|
||||
{
|
||||
mMatrix[i1][i0] = (Real)0;
|
||||
mMatrix[i0][i1] = (Real)0;
|
||||
}
|
||||
}
|
||||
|
||||
// Reordering needed by EigenDecomposition::QLAlgorithm.
|
||||
for (i0 = 1, i3 = 0; i0 < mSize; ++i0, ++i3)
|
||||
{
|
||||
mSubdiagonal[i3] = mSubdiagonal[i0];
|
||||
}
|
||||
mSubdiagonal[mSize-1] = (Real)0;
|
||||
|
||||
mIsRotation = ((mSize % 2) == 0);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
template <typename Real>
|
||||
bool EigenDecomposition<Real>::QLAlgorithm ()
|
||||
{
|
||||
// TODO: This is Numerical Recipes in C code. Rewrite to avoid
|
||||
// copyright issues.
|
||||
|
||||
const int iMaxIter = 32;
|
||||
|
||||
for (int i0 = 0; i0 < mSize; ++i0)
|
||||
{
|
||||
int i1;
|
||||
for (i1 = 0; i1 < iMaxIter; ++i1)
|
||||
{
|
||||
int i2;
|
||||
for (i2 = i0; i2 <= mSize - 2; ++i2)
|
||||
{
|
||||
Real tmp = Math<Real>::FAbs(mDiagonal[i2]) +
|
||||
Math<Real>::FAbs(mDiagonal[i2+1]);
|
||||
|
||||
if (Math<Real>::FAbs(mSubdiagonal[i2]) + tmp == tmp)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i2 == i0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Real value0 = (mDiagonal[i0 + 1]
|
||||
- mDiagonal[i0])/(((Real)2)*mSubdiagonal[i0]);
|
||||
Real value1 = Math<Real>::Sqrt(value0*value0 + (Real)1);
|
||||
if (value0 < (Real)0)
|
||||
{
|
||||
value0 = mDiagonal[i2] - mDiagonal[i0]
|
||||
+ mSubdiagonal[i0]/(value0 - value1);
|
||||
}
|
||||
else
|
||||
{
|
||||
value0 = mDiagonal[i2] - mDiagonal[i0]
|
||||
+ mSubdiagonal[i0]/(value0 + value1);
|
||||
}
|
||||
|
||||
Real sn = (Real)1, cs = (Real)1, value2 = (Real)0;
|
||||
for (int i3 = i2 - 1; i3 >= i0; --i3)
|
||||
{
|
||||
Real value3 = sn*mSubdiagonal[i3];
|
||||
Real value4 = cs*mSubdiagonal[i3];
|
||||
if (Math<Real>::FAbs(value3) >= Math<Real>::FAbs(value0))
|
||||
{
|
||||
cs = value0/value3;
|
||||
value1 = Math<Real>::Sqrt(cs*cs + (Real)1);
|
||||
mSubdiagonal[i3 + 1] = value3*value1;
|
||||
sn = ((Real)1)/value1;
|
||||
cs *= sn;
|
||||
}
|
||||
else
|
||||
{
|
||||
sn = value3/value0;
|
||||
value1 = Math<Real>::Sqrt(sn*sn + (Real)1);
|
||||
mSubdiagonal[i3 + 1] = value0*value1;
|
||||
cs = ((Real)1)/value1;
|
||||
sn *= cs;
|
||||
}
|
||||
value0 = mDiagonal[i3 + 1] - value2;
|
||||
value1 = (mDiagonal[i3] - value0)*sn + ((Real)2)*value4*cs;
|
||||
value2 = sn*value1;
|
||||
mDiagonal[i3 + 1] = value0 + value2;
|
||||
value0 = cs*value1 - value4;
|
||||
|
||||
for (int i4 = 0; i4 < mSize; ++i4)
|
||||
{
|
||||
value3 = mMatrix[i4][i3 + 1];
|
||||
mMatrix[i4][i3 + 1] = sn*mMatrix[i4][i3] + cs*value3;
|
||||
mMatrix[i4][i3] = cs*mMatrix[i4][i3] - sn*value3;
|
||||
}
|
||||
}
|
||||
mDiagonal[i0] -= value2;
|
||||
mSubdiagonal[i0] = value0;
|
||||
mSubdiagonal[i2] = (Real)0;
|
||||
}
|
||||
if (i1 == iMaxIter)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
template <typename Real>
|
||||
void EigenDecomposition<Real>::DecreasingSort ()
|
||||
{
|
||||
// Sort the eigenvalues in decreasing order, e[0] >= ... >= e[mSize-1]
|
||||
for (int i0 = 0, i1; i0 <= mSize - 2; ++i0)
|
||||
{
|
||||
// Locate the maximum eigenvalue.
|
||||
i1 = i0;
|
||||
Real maxValue = mDiagonal[i1];
|
||||
int i2;
|
||||
for (i2 = i0 + 1; i2 < mSize; ++i2)
|
||||
{
|
||||
if (mDiagonal[i2] > maxValue)
|
||||
{
|
||||
i1 = i2;
|
||||
maxValue = mDiagonal[i1];
|
||||
}
|
||||
}
|
||||
|
||||
if (i1 != i0)
|
||||
{
|
||||
// Swap the eigenvalues.
|
||||
mDiagonal[i1] = mDiagonal[i0];
|
||||
mDiagonal[i0] = maxValue;
|
||||
|
||||
// Swap the eigenvectors corresponding to the eigenvalues.
|
||||
for (i2 = 0; i2 < mSize; ++i2)
|
||||
{
|
||||
Real tmp = mMatrix[i2][i0];
|
||||
mMatrix[i2][i0] = mMatrix[i2][i1];
|
||||
mMatrix[i2][i1] = tmp;
|
||||
mIsRotation = !mIsRotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
template <typename Real>
|
||||
void EigenDecomposition<Real>::IncreasingSort ()
|
||||
{
|
||||
// Sort the eigenvalues in increasing order, e[0] <= ... <= e[mSize-1]
|
||||
for (int i0 = 0, i1; i0 <= mSize - 2; ++i0)
|
||||
{
|
||||
// Locate the minimum eigenvalue.
|
||||
i1 = i0;
|
||||
Real minValue = mDiagonal[i1];
|
||||
int i2;
|
||||
for (i2 = i0 + 1; i2 < mSize; ++i2)
|
||||
{
|
||||
if (mDiagonal[i2] < minValue)
|
||||
{
|
||||
i1 = i2;
|
||||
minValue = mDiagonal[i1];
|
||||
}
|
||||
}
|
||||
|
||||
if (i1 != i0)
|
||||
{
|
||||
// Swap the eigenvalues.
|
||||
mDiagonal[i1] = mDiagonal[i0];
|
||||
mDiagonal[i0] = minValue;
|
||||
|
||||
// Swap the eigenvectors corresponding to the eigenvalues.
|
||||
for (i2 = 0; i2 < mSize; ++i2)
|
||||
{
|
||||
Real tmp = mMatrix[i2][i0];
|
||||
mMatrix[i2][i0] = mMatrix[i2][i1];
|
||||
mMatrix[i2][i1] = tmp;
|
||||
mIsRotation = !mIsRotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
template <typename Real>
|
||||
void EigenDecomposition<Real>::GuaranteeRotation ()
|
||||
{
|
||||
if (!mIsRotation)
|
||||
{
|
||||
// Change sign on the first column.
|
||||
for (int row = 0; row < mSize; ++row)
|
||||
{
|
||||
mMatrix[row][0] = -mMatrix[row][0];
|
||||
}
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Explicit instantiation.
|
||||
//----------------------------------------------------------------------------
|
||||
template WM5_MATHEMATICS_ITEM
|
||||
class EigenDecomposition<float>;
|
||||
|
||||
template WM5_MATHEMATICS_ITEM
|
||||
class EigenDecomposition<double>;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template <typename Real>
|
||||
Line3<Real> OrthogonalLineFit3 (int numPoints, const Vector3<Real>* points)
|
||||
{
|
||||
Line3<Real> line(Vector3<Real>(3), Vector3<Real>(3));
|
||||
|
||||
// Compute the mean of the points.
|
||||
line.Origin = points[0];
|
||||
int i;
|
||||
for (i = 1; i < numPoints; i++)
|
||||
{
|
||||
line.Origin += points[i];
|
||||
}
|
||||
Real invNumPoints = ((Real)1)/numPoints;
|
||||
line.Origin *= invNumPoints;
|
||||
|
||||
// Compute the covariance matrix of the points.
|
||||
Real sumXX = (Real)0, sumXY = (Real)0, sumXZ = (Real)0;
|
||||
Real sumYY = (Real)0, sumYZ = (Real)0, sumZZ = (Real)0;
|
||||
for (i = 0; i < numPoints; i++)
|
||||
{
|
||||
Vector3<Real> diff = points[i] - line.Origin;
|
||||
sumXX += diff[0]*diff[0];
|
||||
sumXY += diff[0]*diff[1];
|
||||
sumXZ += diff[0]*diff[2];
|
||||
sumYY += diff[1]*diff[1];
|
||||
sumYZ += diff[1]*diff[2];
|
||||
sumZZ += diff[2]*diff[2];
|
||||
}
|
||||
|
||||
sumXX *= invNumPoints;
|
||||
sumXY *= invNumPoints;
|
||||
sumXZ *= invNumPoints;
|
||||
sumYY *= invNumPoints;
|
||||
sumYZ *= invNumPoints;
|
||||
sumZZ *= invNumPoints;
|
||||
|
||||
// Set up the eigensolver.
|
||||
EigenDecomposition<Real> esystem(3);
|
||||
esystem(0,0) = sumYY+sumZZ;
|
||||
esystem(0,1) = -sumXY;
|
||||
esystem(0,2) = -sumXZ;
|
||||
esystem(1,0) = esystem(0,1);
|
||||
esystem(1,1) = sumXX+sumZZ;
|
||||
esystem(1,2) = -sumYZ;
|
||||
esystem(2,0) = esystem(0,2);
|
||||
esystem(2,1) = esystem(1,2);
|
||||
esystem(2,2) = sumXX+sumYY;
|
||||
|
||||
// Compute eigenstuff, smallest eigenvalue is in last position.
|
||||
esystem.Solve(false);
|
||||
|
||||
// Unit-length direction for best-fit line.
|
||||
line.Direction = esystem.GetEigenvector(2);
|
||||
|
||||
return line;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Explicit instantiation.
|
||||
//----------------------------------------------------------------------------
|
||||
template WM5_MATHEMATICS_ITEM
|
||||
Line3<float> OrthogonalLineFit3<float> (int, const Vector3<float>*);
|
||||
|
||||
template WM5_MATHEMATICS_ITEM
|
||||
Line3<double> OrthogonalLineFit3<double> (int, const Vector3<double>*);
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
355
tjp/core/math/detail/Wm5.h
Normal file
355
tjp/core/math/detail/Wm5.h
Normal file
@@ -0,0 +1,355 @@
|
||||
//
|
||||
// Wm5.h
|
||||
// algorithm
|
||||
//
|
||||
// Created by Timothy Prepscius on 5/3/18.
|
||||
// Copyright © 2018 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <memory.h>
|
||||
#include <math.h>
|
||||
|
||||
namespace Wm5 {
|
||||
|
||||
#define WM5_MATHEMATICS_ITEM
|
||||
#define assertion(...)
|
||||
|
||||
template <typename T>
|
||||
T *new1(size_t size)
|
||||
{
|
||||
return new T[size];
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void delete1(T *t)
|
||||
{
|
||||
delete[] t;
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
template <typename Real>
|
||||
struct Math
|
||||
{
|
||||
WM5_MATHEMATICS_ITEM static const Real ZERO_TOLERANCE;
|
||||
|
||||
static Real FAbs (Real value);
|
||||
static Real Sqrt (Real value);
|
||||
} ;
|
||||
|
||||
typedef Math<float> Mathf;
|
||||
typedef Math<double> Mathd;
|
||||
|
||||
// -----
|
||||
|
||||
template <typename Real>
|
||||
class GVector
|
||||
{
|
||||
public:
|
||||
// Construction and destruction.
|
||||
GVector (int size = 0);
|
||||
GVector (int size, const Real* tuple);
|
||||
GVector (const GVector& vec);
|
||||
~GVector ();
|
||||
|
||||
// Coordinate access.
|
||||
void SetSize (int size);
|
||||
inline int GetSize () const;
|
||||
inline operator const Real* () const;
|
||||
inline operator Real* ();
|
||||
inline const Real& operator[] (int i) const;
|
||||
inline Real& operator[] (int i);
|
||||
|
||||
// Assignment.
|
||||
GVector& operator= (const GVector& vec);
|
||||
|
||||
// Comparison (for use by STL containers).
|
||||
bool operator== (const GVector& vec) const;
|
||||
bool operator!= (const GVector& vec) const;
|
||||
bool operator< (const GVector& vec) const;
|
||||
bool operator<= (const GVector& vec) const;
|
||||
bool operator> (const GVector& vec) const;
|
||||
bool operator>= (const GVector& vec) const;
|
||||
|
||||
// Arithmetic operations.
|
||||
GVector operator+ (const GVector& vec) const;
|
||||
GVector operator- (const GVector& vec) const;
|
||||
GVector operator* (Real scalar) const;
|
||||
GVector operator/ (Real scalar) const;
|
||||
GVector operator- () const;
|
||||
|
||||
friend GVector operator* (Real scalar, const GVector& vec)
|
||||
{
|
||||
return vec*scalar;
|
||||
}
|
||||
|
||||
// Arithmetic updates.
|
||||
GVector& operator+= (const GVector& vec);
|
||||
GVector& operator-= (const GVector& vec);
|
||||
GVector& operator*= (Real scalar);
|
||||
GVector& operator/= (Real scalar);
|
||||
|
||||
// Vector operations.
|
||||
Real Length () const;
|
||||
Real SquaredLength () const;
|
||||
Real Dot (const GVector& vec) const;
|
||||
Real Normalize (Real epsilon = Math<Real>::ZERO_TOLERANCE);
|
||||
|
||||
protected:
|
||||
int mSize;
|
||||
Real* mTuple;
|
||||
};
|
||||
|
||||
typedef GVector<float> GVectorf;
|
||||
typedef GVector<double> GVectord;
|
||||
|
||||
// -----
|
||||
|
||||
template <typename Real>
|
||||
class GMatrix
|
||||
{
|
||||
public:
|
||||
// Construction and destruction.
|
||||
GMatrix (int rows = 0, int columns = 0);
|
||||
GMatrix (int rows, int columns, const Real* entry);
|
||||
GMatrix (int rows, int columns, const Real** matrix);
|
||||
GMatrix (const GMatrix& mat);
|
||||
~GMatrix ();
|
||||
|
||||
// Coordinate access.
|
||||
void SetSize (int rows, int columns);
|
||||
inline void GetSize (int& rows, int& columns) const;
|
||||
inline int GetRows () const;
|
||||
inline int GetColumns () const;
|
||||
inline int GetQuantity () const;
|
||||
inline operator const Real* () const;
|
||||
inline operator Real* ();
|
||||
inline const Real* operator[] (int row) const;
|
||||
inline Real* operator[] (int row);
|
||||
inline const Real& operator() (int row, int column) const;
|
||||
inline Real& operator() (int row, int column);
|
||||
void SwapRows (int row0, int row1);
|
||||
void SetRow (int row, const GVector<Real>& vec);
|
||||
GVector<Real> GetRow (int row) const;
|
||||
void SetColumn (int column, const GVector<Real>& vec);
|
||||
GVector<Real> GetColumn (int column) const;
|
||||
void SetMatrix (int rows, int columns, const Real* entry);
|
||||
void SetMatrix (int rows, int columns, const Real** matrix);
|
||||
void GetColumnMajor (Real* columnMajor) const;
|
||||
|
||||
// Assignment.
|
||||
GMatrix& operator= (const GMatrix& mat);
|
||||
|
||||
// Comparison (for use by STL containers).
|
||||
bool operator== (const GMatrix& mat) const;
|
||||
bool operator!= (const GMatrix& mat) const;
|
||||
bool operator< (const GMatrix& mat) const;
|
||||
bool operator<= (const GMatrix& mat) const;
|
||||
bool operator> (const GMatrix& mat) const;
|
||||
bool operator>= (const GMatrix& mat) const;
|
||||
|
||||
// Arithmetic operations.
|
||||
GMatrix operator+ (const GMatrix& mat) const;
|
||||
GMatrix operator- (const GMatrix& mat) const;
|
||||
GMatrix operator* (const GMatrix& mat) const;
|
||||
GMatrix operator* (Real fScalar) const;
|
||||
GMatrix operator/ (Real fScalar) const;
|
||||
GMatrix operator- () const;
|
||||
|
||||
// Arithmetic updates.
|
||||
GMatrix& operator+= (const GMatrix& mat);
|
||||
GMatrix& operator-= (const GMatrix& mat);
|
||||
GMatrix& operator*= (Real fScalar);
|
||||
GMatrix& operator/= (Real fScalar);
|
||||
|
||||
// M*vec
|
||||
GVector<Real> operator* (const GVector<Real>& vec) const;
|
||||
|
||||
// u^T*M*v
|
||||
Real QForm (const GVector<Real>& u, const GVector<Real>& v) const;
|
||||
|
||||
// M^T
|
||||
GMatrix Transpose () const;
|
||||
|
||||
// M^T*mat
|
||||
GMatrix TransposeTimes (const GMatrix& mat) const;
|
||||
|
||||
// M*mat^T
|
||||
GMatrix TimesTranspose (const GMatrix& mat) const;
|
||||
|
||||
// M^T*mat^T
|
||||
GMatrix TransposeTimesTranspose (const GMatrix& mat) const;
|
||||
|
||||
// Inversion. The matrix must be square. The function returns 'true'
|
||||
// whenever the matrix is square and invertible.
|
||||
bool GetInverse (GMatrix<Real>& inverse) const;
|
||||
|
||||
// c * M
|
||||
friend GMatrix<Real> operator* (Real scalar, const GMatrix<Real>& mat)
|
||||
{
|
||||
return mat*scalar;
|
||||
}
|
||||
|
||||
// v^T * M
|
||||
friend GVector<Real> operator* (const GVector<Real>& vec,
|
||||
const GMatrix<Real>& mat)
|
||||
{
|
||||
assertion(vec.GetSize() == mat.GetRows(), "Mismatch in operator*\n");
|
||||
GVector<Real> prod(mat.GetColumns());
|
||||
Real* entry = prod;
|
||||
for (int c = 0; c < mat.GetColumns(); ++c)
|
||||
{
|
||||
for (int r = 0; r < mat.GetRows(); ++r)
|
||||
{
|
||||
entry[c] += vec[r]*mat[r][c];
|
||||
}
|
||||
}
|
||||
return prod;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Support for allocation and deallocation. The allocation call requires
|
||||
// m_iRows, m_iCols, and m_iQuantity to have already been correctly
|
||||
// initialized.
|
||||
void Allocate (bool setToZero);
|
||||
void Deallocate ();
|
||||
|
||||
int mRows, mColumns, mQuantity;
|
||||
|
||||
// The matrix is stored in row-major form as a 1-dimensional array.
|
||||
Real* mData;
|
||||
|
||||
// An array of pointers to the rows of the matrix. The separation of
|
||||
// row pointers and actual data supports swapping of rows in linear
|
||||
// algebraic algorithms such as solving linear systems of equations.
|
||||
Real** mEntry;
|
||||
};
|
||||
|
||||
|
||||
typedef GMatrix<float> GMatrixf;
|
||||
typedef GMatrix<double> GMatrixd;
|
||||
|
||||
// -----
|
||||
|
||||
|
||||
template <typename Real>
|
||||
class WM5_MATHEMATICS_ITEM EigenDecomposition
|
||||
{
|
||||
public:
|
||||
// Construction and destruction. The matrix of an eigensystem must be
|
||||
// symmetric.
|
||||
EigenDecomposition (int size);
|
||||
// EigenDecomposition (const Matrix2<Real>& mat);
|
||||
// EigenDecomposition (const Matrix3<Real>& mat);
|
||||
EigenDecomposition (const GMatrix<Real>& mat);
|
||||
~EigenDecomposition ();
|
||||
|
||||
// Set the matrix for the eigensystem.
|
||||
Real& operator() (int row, int column);
|
||||
// EigenDecomposition& operator= (const Matrix2<Real>& mat);
|
||||
// EigenDecomposition& operator= (const Matrix3<Real>& mat);
|
||||
EigenDecomposition& operator= (const GMatrix<Real>& mat);
|
||||
|
||||
// Solve the eigensystem. Set 'increasingSort' to 'true' when you want
|
||||
// the eigenvalues to be sorted in increasing order; otherwise, the
|
||||
// eigenvalues are sorted in decreasing order.
|
||||
void Solve (bool increasingSort);
|
||||
|
||||
// Get the results. The calls to GetEigenvector2, GetEigenvectors2,
|
||||
// GetEigenvector3, and GetEigenvector3 should be made only if you know
|
||||
// that the eigensystem is of the corresponding size.
|
||||
Real GetEigenvalue (int i) const;
|
||||
const Real* GetEigenvalues () const;
|
||||
// Vector2<Real> GetEigenvector2 (int i) const;
|
||||
// Matrix2<Real> GetEigenvectors2 () const;
|
||||
// Vector3<Real> GetEigenvector3 (int i) const;
|
||||
// Matrix3<Real> GetEigenvectors3 () const;
|
||||
GVector<Real> GetEigenvector (int i) const;
|
||||
const GMatrix<Real>& GetEigenvectors () const;
|
||||
|
||||
private:
|
||||
int mSize;
|
||||
GMatrix<Real> mMatrix;
|
||||
Real* mDiagonal;
|
||||
Real* mSubdiagonal;
|
||||
|
||||
// For odd size matrices, the Householder reduction involves an odd
|
||||
// number of reflections. The product of these is a reflection. The
|
||||
// QL algorithm uses rotations for further reductions. The final
|
||||
// orthogonal matrix whose columns are the eigenvectors is a reflection,
|
||||
// so its determinant is -1. For even size matrices, the Householder
|
||||
// reduction involves an even number of reflections whose product is a
|
||||
// rotation. The final orthogonal matrix has determinant +1. Many
|
||||
// algorithms that need an eigendecomposition want a rotation matrix.
|
||||
// We want to guarantee this is the case, so mRotation keeps track of
|
||||
// this. The DecrSort and IncrSort further complicate the issue since
|
||||
// they swap columns of the orthogonal matrix, causing the matrix to
|
||||
// toggle between rotation and reflection. The value mRotation must
|
||||
// be toggled accordingly.
|
||||
bool mIsRotation;
|
||||
void GuaranteeRotation ();
|
||||
|
||||
// Householder reduction to tridiagonal form.
|
||||
void Tridiagonal2 ();
|
||||
void Tridiagonal3 ();
|
||||
void TridiagonalN ();
|
||||
|
||||
// QL algorithm with implicit shifting. This function is called for
|
||||
// tridiagonal matrices.
|
||||
bool QLAlgorithm ();
|
||||
|
||||
// Sort eigenvalues from largest to smallest.
|
||||
void DecreasingSort ();
|
||||
|
||||
// Sort eigenvalues from smallest to largest.
|
||||
void IncreasingSort ();
|
||||
};
|
||||
|
||||
typedef EigenDecomposition<float> EigenDecompositionf;
|
||||
typedef EigenDecomposition<double> EigenDecompositiond;
|
||||
|
||||
|
||||
// -----
|
||||
|
||||
template<typename Real>
|
||||
using Vector3 = GVector<Real>;
|
||||
|
||||
template <typename Real>
|
||||
class Line3
|
||||
{
|
||||
public:
|
||||
// The line is represented as P+t*D where P is the line origin, D is a
|
||||
// unit-length direction vector, and t is any real number. The user must
|
||||
// ensure that D is indeed unit length.
|
||||
|
||||
// Construction and destruction.
|
||||
Line3 () {}; // uninitialized
|
||||
~Line3 () {};
|
||||
|
||||
Line3 (const Vector3<Real>& origin, const Vector3<Real>& direction) :
|
||||
Origin(origin),
|
||||
Direction(direction)
|
||||
{
|
||||
}
|
||||
|
||||
Vector3<Real> Origin, Direction;
|
||||
};
|
||||
|
||||
typedef Line3<float> Line3f;
|
||||
typedef Line3<double> Line3d;
|
||||
|
||||
// -------
|
||||
|
||||
// Least-squares fit of a line to (x,y,z) data by using distance measurements
|
||||
// orthogonal to the proposed line.
|
||||
template <typename Real> WM5_MATHEMATICS_ITEM
|
||||
Line3<Real> OrthogonalLineFit3 (int numPoints, const Vector3<Real>* points);
|
||||
|
||||
// ------
|
||||
|
||||
#include "Wm5.inl"
|
||||
|
||||
} // namespace
|
||||
1089
tjp/core/math/detail/Wm5.inl
Normal file
1089
tjp/core/math/detail/Wm5.inl
Normal file
File diff suppressed because it is too large
Load Diff
86
tjp/core/math/mean.hpp
Executable file
86
tjp/core/math/mean.hpp
Executable file
@@ -0,0 +1,86 @@
|
||||
//
|
||||
// Math.hpp
|
||||
// amoeba
|
||||
//
|
||||
// Created by Timothy Prepscius on 12/30/16.
|
||||
// Copyright © 2016 Timothy Prepscius. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp::core::math {
|
||||
|
||||
template<typename T>
|
||||
struct Mean_SumDivide
|
||||
{
|
||||
T t = zero<T>();
|
||||
size_t count = 0;
|
||||
|
||||
void add(const T &v)
|
||||
{
|
||||
t = t + v;
|
||||
count++;
|
||||
}
|
||||
|
||||
T mean() const
|
||||
{
|
||||
return t / count;
|
||||
}
|
||||
};
|
||||
|
||||
// https://www.geeksforgeeks.org/program-for-average-of-an-array-without-running-into-overflow/
|
||||
template<typename T>
|
||||
struct Mean_AddDivide
|
||||
{
|
||||
T t = zero<T>();
|
||||
size_t count = 0;
|
||||
|
||||
void add(const T &v)
|
||||
{
|
||||
++count;
|
||||
t = t + (v - t) / (count);
|
||||
}
|
||||
|
||||
T mean() const
|
||||
{
|
||||
return t / count;
|
||||
}
|
||||
} ;
|
||||
|
||||
// https://www.geeksforgeeks.org/compute-average-two-numbers-without-overflow/
|
||||
template<typename T>
|
||||
struct Mean_AddDivideMod
|
||||
{
|
||||
T t = zero<T>();
|
||||
size_t count = 0;
|
||||
|
||||
void add(const T &v)
|
||||
{
|
||||
++count;
|
||||
t = t + (v - t) / (count);
|
||||
}
|
||||
|
||||
T mean() const
|
||||
{
|
||||
return t / count;
|
||||
}
|
||||
} ;
|
||||
|
||||
template<typename T, typename U>
|
||||
auto mean_(const U &u)
|
||||
{
|
||||
T t;
|
||||
for (auto &v: u)
|
||||
t.add(v);
|
||||
|
||||
return t.mean();
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
auto mean(const U &u)
|
||||
{
|
||||
return mean_<Mean_SumDivide<typename U::value_type>>(u);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user