Task: Angles (geometric), normalization and conversion


C++: #include <functional>
#include <iostream>
#include <iomanip>
#include <math.h>
#include <sstream>
#include <vector>
#include <boost/algorithm/string.hpp>

template<typename T>
T normalize(T a, double b) { return std::fmod(a, b); }

inline double d2d(double a) { return normalize<double>(a, 360); }
inline double g2g(double a) { return normalize<double>(a, 400); }
inline double m2m(double a) { return normalize<double>(a, 6400); }
inline double r2r(double a) { return normalize<double>(a, 2*M_PI); }

double d2g(double a) { return g2g(a * 10 / 9); }
double d2m(double a) { return m2m(a * 160 / 9); }
double d2r(double a) { return r2r(a * M_PI / 180); }
double g2d(double a) { return d2d(a * 9 / 10); }
double g2m(double a) { return m2m(a * 16); }
double g2r(double a) { return r2r(a * M_PI / 200); }
double m2d(double a) { return d2d(a * 9 / 160); }
double m2g(double a) { return g2g(a / 16); }
double m2r(double a) { return r2r(a * M_PI / 3200); }
double r2d(double a) { return d2d(a * 180 / M_PI); }
double r2g(double a) { return g2g(a * 200 / M_PI); }
double r2m(double a) { return m2m(a * 3200 / M_PI); }

void print(const std::vector<double> &values, const char *s, std::function<double(double)> f) {
    using namespace std;
    ostringstream out;
    out << "                  ┌───────────────────┐\n";
    out << "                  │ " << setw(17) << s << " │\n";
    out << "┌─────────────────┼───────────────────┤\n";
    for (double i : values)
        out << "│ " << setw(15) << fixed << i << defaultfloat << " │ " << setw(17) << fixed << f(i) << defaultfloat << " │\n";
    out << "└─────────────────┴───────────────────┘\n";
    auto str = out.str();
    boost::algorithm::replace_all(str, ".000000", "       ");
    cout << str;
}

int main() {
    std::vector<double> values = { -2, -1, 0, 1, 2, 6.2831853, 16, 57.2957795, 359, 399, 6399, 1000000 };
    print(values, "normalized (deg)", d2d);
    print(values, "normalized (grad)", g2g);
    print(values, "normalized (mil)", m2m);
    print(values, "normalized (rad)", r2r);

    print(values, "deg -> grad ", d2g);
    print(values, "deg -> mil ", d2m);
    print(values, "deg -> rad ", d2r);

    print(values, "grad -> deg ", g2d);
    print(values, "grad -> mil ", g2m);
    print(values, "grad -> rad ", g2r);

    print(values, "mil -> deg ", m2d);
    print(values, "mil -> grad ", m2g);
    print(values, "mil -> rad ", m2r);

    print(values, "rad -> deg ", r2d);
    print(values, "rad -> grad ", r2g);
    print(values, "rad -> mil ", r2m);

    return 0;
}



Go: package main

import (
    "fmt"
    "math"
    "strconv"
    "strings"
)

func d2d(d float64) float64 { return math.Mod(d, 360) }

func g2g(g float64) float64 { return math.Mod(g, 400) }

func m2m(m float64) float64 { return math.Mod(m, 6400) }

func r2r(r float64) float64 { return math.Mod(r, 2*math.Pi) }

func d2g(d float64) float64 { return d2d(d) * 400 / 360 }

func d2m(d float64) float64 { return d2d(d) * 6400 / 360 }

func d2r(d float64) float64 { return d2d(d) * math.Pi / 180 }

func g2d(g float64) float64 { return g2g(g) * 360 / 400 }

func g2m(g float64) float64 { return g2g(g) * 6400 / 400 }

func g2r(g float64) float64 { return g2g(g) * math.Pi / 200 }

func m2d(m float64) float64 { return m2m(m) * 360 / 6400 }

func m2g(m float64) float64 { return m2m(m) * 400 / 6400 }

func m2r(m float64) float64 { return m2m(m) * math.Pi / 3200 }

func r2d(r float64) float64 { return r2r(r) * 180 / math.Pi }

func r2g(r float64) float64 { return r2r(r) * 200 / math.Pi }

func r2m(r float64) float64 { return r2r(r) * 3200 / math.Pi }


func s(f float64) string {
    wf := strings.Split(strconv.FormatFloat(f, 'g', 15, 64), ".")
    if len(wf) == 1 {
        return fmt.Sprintf("%7s        ", wf[0])
    }
    le := len(wf[1])
    if le > 7 {
        le = 7
    }
    return fmt.Sprintf("%7s.%-7s", wf[0], wf[1][:le])
}

func main() {
    angles := []float64{-2, -1, 0, 1, 2, 6.2831853, 16, 57.2957795,
        359, 399, 6399, 1000000}
    ft := "%s %s %s %s %s\n"
    fmt.Printf(ft, "    degrees    ", "normalized degs", "    gradians   ", "     mils      ", "     radians")
    for _, a := range angles {
        fmt.Printf(ft, s(a), s(d2d(a)), s(d2g(a)), s(d2m(a)), s(d2r(a)))
    }
    fmt.Printf(ft, "\n   gradians    ", "normalized grds", "    degrees    ", "     mils      ", "     radians")
    for _, a := range angles {
        fmt.Printf(ft, s(a), s(g2g(a)), s(g2d(a)), s(g2m(a)), s(g2r(a)))
    }
    fmt.Printf(ft, "\n     mils      ", "normalized mils", "    degrees    ", "   gradians    ", "     radians")
    for _, a := range angles {
        fmt.Printf(ft, s(a), s(m2m(a)), s(m2d(a)), s(m2g(a)), s(m2r(a)))
    }
    fmt.Printf(ft, "\n    radians    ", "normalized rads", "    degrees    ", "   gradians    ", "      mils  ")
    for _, a := range angles {
        fmt.Printf(ft, s(a), s(r2r(a)), s(r2d(a)), s(r2g(a)), s(r2m(a)))
    }
}