1*d19ef5a2SAaron LI /*-
2*d19ef5a2SAaron LI * SPDX-License-Identifier: BSD-3-Clause
3*d19ef5a2SAaron LI *
4*d19ef5a2SAaron LI * Copyright (c) 2019-2020 The DragonFly Project. All rights reserved.
5*d19ef5a2SAaron LI *
6*d19ef5a2SAaron LI * This code is derived from software contributed to The DragonFly Project
7*d19ef5a2SAaron LI * by Aaron LI <aly@aaronly.me>
8*d19ef5a2SAaron LI *
9*d19ef5a2SAaron LI * Redistribution and use in source and binary forms, with or without
10*d19ef5a2SAaron LI * modification, are permitted provided that the following conditions
11*d19ef5a2SAaron LI * are met:
12*d19ef5a2SAaron LI *
13*d19ef5a2SAaron LI * 1. Redistributions of source code must retain the above copyright
14*d19ef5a2SAaron LI * notice, this list of conditions and the following disclaimer.
15*d19ef5a2SAaron LI * 2. Redistributions in binary form must reproduce the above copyright
16*d19ef5a2SAaron LI * notice, this list of conditions and the following disclaimer in
17*d19ef5a2SAaron LI * the documentation and/or other materials provided with the
18*d19ef5a2SAaron LI * distribution.
19*d19ef5a2SAaron LI * 3. Neither the name of The DragonFly Project nor the names of its
20*d19ef5a2SAaron LI * contributors may be used to endorse or promote products derived
21*d19ef5a2SAaron LI * from this software without specific, prior written permission.
22*d19ef5a2SAaron LI *
23*d19ef5a2SAaron LI * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24*d19ef5a2SAaron LI * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25*d19ef5a2SAaron LI * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26*d19ef5a2SAaron LI * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27*d19ef5a2SAaron LI * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28*d19ef5a2SAaron LI * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
29*d19ef5a2SAaron LI * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30*d19ef5a2SAaron LI * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
31*d19ef5a2SAaron LI * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32*d19ef5a2SAaron LI * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33*d19ef5a2SAaron LI * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34*d19ef5a2SAaron LI * SUCH DAMAGE.
35*d19ef5a2SAaron LI *
36*d19ef5a2SAaron LI * Reference:
37*d19ef5a2SAaron LI * Calendrical Calculations, The Ultimate Edition (4th Edition)
38*d19ef5a2SAaron LI * by Edward M. Reingold and Nachum Dershowitz
39*d19ef5a2SAaron LI * 2018, Cambridge University Press
40*d19ef5a2SAaron LI */
41*d19ef5a2SAaron LI
42*d19ef5a2SAaron LI #include <err.h>
43*d19ef5a2SAaron LI #include <math.h>
44*d19ef5a2SAaron LI #include <stdbool.h>
45*d19ef5a2SAaron LI #include <stddef.h>
46*d19ef5a2SAaron LI #include <stdio.h>
47*d19ef5a2SAaron LI #include <stdlib.h>
48*d19ef5a2SAaron LI #include <string.h>
49*d19ef5a2SAaron LI
50*d19ef5a2SAaron LI #include "utils.h"
51*d19ef5a2SAaron LI
52*d19ef5a2SAaron LI
53*d19ef5a2SAaron LI /*
54*d19ef5a2SAaron LI * Calculate the polynomial: c[0] + c[1] * x + ... + c[n-1] * x^(n-1)
55*d19ef5a2SAaron LI */
56*d19ef5a2SAaron LI double
poly(double x,const double * coefs,size_t n)57*d19ef5a2SAaron LI poly(double x, const double *coefs, size_t n)
58*d19ef5a2SAaron LI {
59*d19ef5a2SAaron LI double p = 0.0;
60*d19ef5a2SAaron LI double t = 1.0;
61*d19ef5a2SAaron LI for (size_t i = 0; i < n; i++) {
62*d19ef5a2SAaron LI p += t * coefs[i];
63*d19ef5a2SAaron LI t *= x;
64*d19ef5a2SAaron LI }
65*d19ef5a2SAaron LI return p;
66*d19ef5a2SAaron LI }
67*d19ef5a2SAaron LI
68*d19ef5a2SAaron LI /*
69*d19ef5a2SAaron LI * Use bisection search to find the inverse of the given angular function
70*d19ef5a2SAaron LI * $f(x) at value $y (degrees) within time interval [$a, $b].
71*d19ef5a2SAaron LI * Ref: Sec.(1.8), Eq.(1.36)
72*d19ef5a2SAaron LI */
73*d19ef5a2SAaron LI double
invert_angular(double (* f)(double),double y,double a,double b)74*d19ef5a2SAaron LI invert_angular(double (*f)(double), double y, double a, double b)
75*d19ef5a2SAaron LI {
76*d19ef5a2SAaron LI static const double eps = 1e-6;
77*d19ef5a2SAaron LI double x;
78*d19ef5a2SAaron LI
79*d19ef5a2SAaron LI do {
80*d19ef5a2SAaron LI x = (a + b) / 2.0;
81*d19ef5a2SAaron LI if (mod_f(f(x) - y, 360) < 180.0)
82*d19ef5a2SAaron LI b = x;
83*d19ef5a2SAaron LI else
84*d19ef5a2SAaron LI a = x;
85*d19ef5a2SAaron LI } while (fabs(a-b) >= eps);
86*d19ef5a2SAaron LI
87*d19ef5a2SAaron LI return x;
88*d19ef5a2SAaron LI }
89*d19ef5a2SAaron LI
90*d19ef5a2SAaron LI
91*d19ef5a2SAaron LI /*
92*d19ef5a2SAaron LI * Like malloc(3) but exit if allocation fails.
93*d19ef5a2SAaron LI */
94*d19ef5a2SAaron LI void *
xmalloc(size_t size)95*d19ef5a2SAaron LI xmalloc(size_t size)
96*d19ef5a2SAaron LI {
97*d19ef5a2SAaron LI void *ptr = malloc(size);
98*d19ef5a2SAaron LI if (ptr == NULL)
99*d19ef5a2SAaron LI errx(1, "mcalloc(%zu): out of memory", size);
100*d19ef5a2SAaron LI return ptr;
101*d19ef5a2SAaron LI }
102*d19ef5a2SAaron LI
103*d19ef5a2SAaron LI /*
104*d19ef5a2SAaron LI * Like calloc(3) but exit if allocation fails.
105*d19ef5a2SAaron LI */
106*d19ef5a2SAaron LI void *
xcalloc(size_t number,size_t size)107*d19ef5a2SAaron LI xcalloc(size_t number, size_t size)
108*d19ef5a2SAaron LI {
109*d19ef5a2SAaron LI void *ptr = calloc(number, size);
110*d19ef5a2SAaron LI if (ptr == NULL)
111*d19ef5a2SAaron LI errx(1, "xcalloc(%zu, %zu): out of memory", number, size);
112*d19ef5a2SAaron LI return ptr;
113*d19ef5a2SAaron LI }
114*d19ef5a2SAaron LI
115*d19ef5a2SAaron LI /*
116*d19ef5a2SAaron LI * Like realloc(3) but exit if allocation fails.
117*d19ef5a2SAaron LI */
118*d19ef5a2SAaron LI void *
xrealloc(void * ptr,size_t size)119*d19ef5a2SAaron LI xrealloc(void *ptr, size_t size)
120*d19ef5a2SAaron LI {
121*d19ef5a2SAaron LI ptr = realloc(ptr, size);
122*d19ef5a2SAaron LI if (ptr == NULL)
123*d19ef5a2SAaron LI errx(1, "xrealloc: out of memory (size: %zu)", size);
124*d19ef5a2SAaron LI return ptr;
125*d19ef5a2SAaron LI }
126*d19ef5a2SAaron LI
127*d19ef5a2SAaron LI /*
128*d19ef5a2SAaron LI * Like strdup(3) but exit if fail.
129*d19ef5a2SAaron LI */
130*d19ef5a2SAaron LI char *
xstrdup(const char * str)131*d19ef5a2SAaron LI xstrdup(const char *str)
132*d19ef5a2SAaron LI {
133*d19ef5a2SAaron LI char *p = strdup(str);
134*d19ef5a2SAaron LI if (p == NULL)
135*d19ef5a2SAaron LI errx(1, "xstrdup: out of memory (length: %zu)", strlen(str));
136*d19ef5a2SAaron LI return p;
137*d19ef5a2SAaron LI }
138*d19ef5a2SAaron LI
139*d19ef5a2SAaron LI
140*d19ef5a2SAaron LI /*
141*d19ef5a2SAaron LI * Linked list implementation
142*d19ef5a2SAaron LI */
143*d19ef5a2SAaron LI
144*d19ef5a2SAaron LI struct node {
145*d19ef5a2SAaron LI char *name;
146*d19ef5a2SAaron LI void *data;
147*d19ef5a2SAaron LI struct node *next;
148*d19ef5a2SAaron LI };
149*d19ef5a2SAaron LI
150*d19ef5a2SAaron LI /*
151*d19ef5a2SAaron LI * Create a new list node with the given $name and $data.
152*d19ef5a2SAaron LI */
153*d19ef5a2SAaron LI struct node *
list_newnode(char * name,void * data)154*d19ef5a2SAaron LI list_newnode(char *name, void *data)
155*d19ef5a2SAaron LI {
156*d19ef5a2SAaron LI struct node *newp;
157*d19ef5a2SAaron LI
158*d19ef5a2SAaron LI newp = xcalloc(1, sizeof(*newp));
159*d19ef5a2SAaron LI newp->name = name;
160*d19ef5a2SAaron LI newp->data = data;
161*d19ef5a2SAaron LI
162*d19ef5a2SAaron LI return newp;
163*d19ef5a2SAaron LI }
164*d19ef5a2SAaron LI
165*d19ef5a2SAaron LI /*
166*d19ef5a2SAaron LI * Add $newp to the front of list $listp.
167*d19ef5a2SAaron LI */
168*d19ef5a2SAaron LI struct node *
list_addfront(struct node * listp,struct node * newp)169*d19ef5a2SAaron LI list_addfront(struct node *listp, struct node *newp)
170*d19ef5a2SAaron LI {
171*d19ef5a2SAaron LI newp->next = listp;
172*d19ef5a2SAaron LI return newp;
173*d19ef5a2SAaron LI }
174*d19ef5a2SAaron LI
175*d19ef5a2SAaron LI /*
176*d19ef5a2SAaron LI * Lookup the given $name in the list $listp.
177*d19ef5a2SAaron LI * The $cmp function compares two names and return 0 if they equal.
178*d19ef5a2SAaron LI * Return the associated data with the found node, otherwise NULL.
179*d19ef5a2SAaron LI */
180*d19ef5a2SAaron LI bool
list_lookup(struct node * listp,const char * name,int (* cmp)(const char *,const char *),void ** data_out)181*d19ef5a2SAaron LI list_lookup(struct node *listp, const char *name,
182*d19ef5a2SAaron LI int (*cmp)(const char *, const char *), void **data_out)
183*d19ef5a2SAaron LI {
184*d19ef5a2SAaron LI for ( ; listp; listp = listp->next) {
185*d19ef5a2SAaron LI if ((*cmp)(name, listp->name) == 0) {
186*d19ef5a2SAaron LI if (data_out)
187*d19ef5a2SAaron LI *data_out = listp->data;
188*d19ef5a2SAaron LI return true;
189*d19ef5a2SAaron LI }
190*d19ef5a2SAaron LI }
191*d19ef5a2SAaron LI
192*d19ef5a2SAaron LI return false;
193*d19ef5a2SAaron LI }
194*d19ef5a2SAaron LI
195*d19ef5a2SAaron LI /*
196*d19ef5a2SAaron LI * Free all nodes of list $listp.
197*d19ef5a2SAaron LI */
198*d19ef5a2SAaron LI void
list_freeall(struct node * listp,void (* free_name)(void *),void (* free_data)(void *))199*d19ef5a2SAaron LI list_freeall(struct node *listp,
200*d19ef5a2SAaron LI void (*free_name)(void *),
201*d19ef5a2SAaron LI void (*free_data)(void *))
202*d19ef5a2SAaron LI {
203*d19ef5a2SAaron LI struct node *cur;
204*d19ef5a2SAaron LI
205*d19ef5a2SAaron LI while (listp) {
206*d19ef5a2SAaron LI cur = listp;
207*d19ef5a2SAaron LI listp = listp->next;
208*d19ef5a2SAaron LI if (free_name)
209*d19ef5a2SAaron LI (*free_name)(cur->name);
210*d19ef5a2SAaron LI if (free_data)
211*d19ef5a2SAaron LI (*free_data)(cur->data);
212*d19ef5a2SAaron LI free(cur);
213*d19ef5a2SAaron LI }
214*d19ef5a2SAaron LI }
215