aboutsummaryrefslogtreecommitdiff
path: root/src/stdlib/nums.h
blob: 1b757e4e773b5224538c92af128544a156d6e812 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#pragma once

// Type infos and methods for Nums (floating point)

#include <math.h>
#include <stdbool.h>
#include <stdint.h>

#include "datatypes.h"
#include "integers.h"
#include "stdlib.h"
#include "types.h"
#include "util.h"

#define OptionalNum_t double
#define OptionalNum32_t float
#define N32(n) ((float)(n))
#define N64(n) ((double)(n))

Text_t Numヽas_text(const void *f, bool colorize, const TypeInfo_t *type);
PUREFUNC int32_t Numヽcompare(const void *x, const void *y, const TypeInfo_t *type);
PUREFUNC bool Numヽequal(const void *x, const void *y, const TypeInfo_t *type);
CONSTFUNC bool Numヽnear(double a, double b, double ratio, double absolute);
Text_t Numヽpercent(double f, double precision);
double CONSTFUNC Numヽwith_precision(double num, double precision);
double Numヽmod(double num, double modulus);
double Numヽmod1(double num, double modulus);
CONSTFUNC bool Numヽisinf(double n);
CONSTFUNC bool Numヽfinite(double n);
CONSTFUNC bool Numヽisnan(double n);
double Numヽnan(Text_t tag);
CONSTFUNC double Numヽmix(double amount, double x, double y);
OptionalNum_t Numヽparse(Text_t text, Text_t *remainder);
CONSTFUNC bool Numヽis_between(const double x, const double low, const double high);
CONSTFUNC double Numヽclamped(double x, double low, double high);
MACROLIKE CONSTFUNC double Numヽfrom_num32(Num32_t n) { return (double)n; }
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
MACROLIKE CONSTFUNC double Numヽfrom_int(Int_t i, bool truncate) {
    if likely (i.small & 0x1) {
        double ret = (double)(i.small >> 2);
        if unlikely (!truncate && (int64_t)ret != (i.small >> 2))
            fail("Could not convert integer to 64-bit floating point without losing precision: ", i.small >> 2);
        return ret;
    } else {
        double ret = mpz_get_d(*i.big);
        if (!truncate) {
            mpz_t roundtrip;
            mpz_init_set_d(roundtrip, ret);
            if unlikely (mpz_cmp(*i.big, roundtrip) != 0)
                fail("Could not convert integer to 64-bit floating point without losing precision: ", i);
        }
        return ret;
    }
}
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
MACROLIKE CONSTFUNC double Numヽfrom_int64(Int64_t i, bool truncate) {
    double n = (double)i;
    if unlikely (!truncate && (Int64_t)n != i)
        fail("Could not convert integer to 64-bit floating point without losing precision: ", i);
    return n;
}
MACROLIKE CONSTFUNC double Numヽfrom_int32(Int32_t i) { return (double)i; }
MACROLIKE CONSTFUNC double Numヽfrom_int16(Int16_t i) { return (double)i; }
MACROLIKE CONSTFUNC double Numヽfrom_int8(Int8_t i) { return (double)i; }
MACROLIKE CONSTFUNC double Numヽfrom_byte(Byte_t i) { return (double)i; }

extern const TypeInfo_t Numヽinfo;

Text_t Num32ヽas_text(const void *f, bool colorize, const TypeInfo_t *type);
PUREFUNC int32_t Num32ヽcompare(const void *x, const void *y, const TypeInfo_t *type);
PUREFUNC bool Num32ヽequal(const void *x, const void *y, const TypeInfo_t *type);
CONSTFUNC bool Num32ヽnear(float a, float b, float ratio, float absolute);
Text_t Num32ヽpercent(float f, float precision);
float CONSTFUNC Num32ヽwith_precision(float num, float precision);
float Num32ヽmod(float num, float modulus);
float Num32ヽmod1(float num, float modulus);
CONSTFUNC bool Num32ヽisinf(float n);
CONSTFUNC bool Num32ヽfinite(float n);
CONSTFUNC bool Num32ヽisnan(float n);
CONSTFUNC float Num32ヽmix(float amount, float x, float y);
OptionalNum32_t Num32ヽparse(Text_t text, Text_t *remainder);
float Num32ヽnan(Text_t tag);
CONSTFUNC bool Num32ヽis_between(const float x, const float low, const float high);
CONSTFUNC float Num32ヽclamped(float x, float low, float high);
MACROLIKE CONSTFUNC float Num32ヽfrom_num(Num_t n) { return (float)n; }
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
MACROLIKE CONSTFUNC float Num32ヽfrom_int(Int_t i, bool truncate) {
    if likely (i.small & 0x1) {
        float ret = (float)(i.small >> 2);
        if unlikely (!truncate && (int64_t)ret != (i.small >> 2))
            fail("Could not convert integer to 32-bit floating point without losing precision: ", i.small >> 2);
        return ret;
    } else {
        float ret = (float)mpz_get_d(*i.big);
        if (!truncate) {
            mpz_t roundtrip;
            mpz_init_set_d(roundtrip, (double)ret);
            if unlikely (mpz_cmp(*i.big, roundtrip) != 0)
                fail("Could not convert integer to 32-bit floating point without losing precision: ", i);
        }
        return ret;
    }
}
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
MACROLIKE CONSTFUNC float Num32ヽfrom_int64(Int64_t i, bool truncate) {
    float n = (float)i;
    if unlikely (!truncate && (Int64_t)n != i)
        fail("Could not convert integer to 32-bit floating point without losing precision: ", i);
    return n;
}
MACROLIKE CONSTFUNC float Num32ヽfrom_int32(Int32_t i, bool truncate) {
    float n = (float)i;
    if unlikely (!truncate && (Int32_t)n != i)
        fail("Could not convert integer to 32-bit floating point without losing precision: ", i);
    return n;
}
MACROLIKE CONSTFUNC float Num32ヽfrom_int16(Int16_t i) { return (float)i; }
MACROLIKE CONSTFUNC float Num32ヽfrom_int8(Int8_t i) { return (float)i; }
MACROLIKE CONSTFUNC float Num32ヽfrom_byte(Byte_t i) { return (float)i; }

extern const TypeInfo_t Num32ヽinfo;

// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0