swisseph 1.4.1 → 1.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/swisseph/extconf.rb +15 -0
- data/ext/swisseph/swisseph.c +282 -0
- data/lib/swisseph.rb +31 -18
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4d6f0a41f6d7670ef96d6b2d55ecaef8e052654a92e8e860ac7f8f42c72fe5c5
|
|
4
|
+
data.tar.gz: e4eb00865e165d73f78680e0d66421655352af5c6dbfaa09f7e84fb77f4dd32a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d4d06845c78d2eb0f5588aa1fde5c59266483ee1b8f6b9351ae601df8a6768ff4085ff7ac3fce3483f8aeb5de5558592c5ab4ff11427f50dd9c186f9ae7c3178
|
|
7
|
+
data.tar.gz: 2a9a8daff77a5540280fb4c899efb99764abcf1e99434a605dea463f0bca61fcd049eac9da43152306e9acff33002addc84d79c0d8c50e06762d287e0ba2c15e
|
data/ext/swisseph/extconf.rb
CHANGED
|
@@ -54,6 +54,21 @@ if !swisseph_sources_exist || !File.exist?(stamp_file)
|
|
|
54
54
|
fetch_swisseph_with_cmake
|
|
55
55
|
end
|
|
56
56
|
|
|
57
|
+
# Enable thread-local `swed` on Apple too. Upstream sweodef.h gates TLS off for
|
|
58
|
+
# __APPLE__ -- a legacy guard for Apple's old GCC 4.2, which lacked __thread.
|
|
59
|
+
# Modern clang supports it on Intel and Apple Silicon, so dropping the exclusion
|
|
60
|
+
# makes libswe per-thread reentrant on macOS as it already is on Linux (verified
|
|
61
|
+
# under ThreadSanitizer). Idempotent; runs whether or not sources were re-fetched.
|
|
62
|
+
sweodef = File.join(__dir__, 'sweodef.h')
|
|
63
|
+
if File.exist?(sweodef)
|
|
64
|
+
src = File.read(sweodef)
|
|
65
|
+
patched = src.sub('!defined(TLSOFF) && !defined( __APPLE__ )', '!defined(TLSOFF)')
|
|
66
|
+
if patched != src
|
|
67
|
+
File.write(sweodef, patched)
|
|
68
|
+
puts 'Patched sweodef.h to enable thread-local swed on Apple.'
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
57
72
|
# Get all C source files, excluding utility programs
|
|
58
73
|
$srcs = Dir.glob('*.c').select { |f|
|
|
59
74
|
!['swephgen4.c', 'swemini.c', 'sweasp.c', 'swevents.c', 'swetest.c', 'sweephe4.c'].include?(f)
|
data/ext/swisseph/swisseph.c
CHANGED
|
@@ -21,6 +21,7 @@ along with Swisseph. If not, see <http://www.gnu.org/licenses/>.
|
|
|
21
21
|
|
|
22
22
|
// https://docs.ruby-lang.org/en/3.0/extension_rdoc.html
|
|
23
23
|
#include <ruby.h>
|
|
24
|
+
#include <string.h>
|
|
24
25
|
#include "swephexp.h"
|
|
25
26
|
|
|
26
27
|
// Module Name
|
|
@@ -1660,6 +1661,280 @@ static VALUE t_swe_lun_eclipse_how(VALUE self, VALUE tjd, VALUE ifl, VALUE lon,
|
|
|
1660
1661
|
return output;
|
|
1661
1662
|
}
|
|
1662
1663
|
|
|
1664
|
+
/*
|
|
1665
|
+
* Extended atmospheric refraction, with geographic altitude and lapse rate.
|
|
1666
|
+
* double swe_refrac_extended(double inalt, double geoalt, double atpress, double attemp,
|
|
1667
|
+
* double lapse_rate, int32 calc_flag, double *dret);
|
|
1668
|
+
* calc_flag: SE_TRUE_TO_APP or SE_APP_TO_TRUE
|
|
1669
|
+
* Returns [result, dret[4]] where dret is
|
|
1670
|
+
* [0] true altitude (if possible), [1] apparent altitude,
|
|
1671
|
+
* [2] refraction, [3] dip of horizon
|
|
1672
|
+
*/
|
|
1673
|
+
static VALUE t_swe_refrac_extended(VALUE self, VALUE inalt, VALUE geoalt, VALUE atpress, VALUE attemp, VALUE lapse_rate, VALUE calc_flag)
|
|
1674
|
+
{
|
|
1675
|
+
double dret[20];
|
|
1676
|
+
double result = swe_refrac_extended(NUM2DBL(inalt), NUM2DBL(geoalt), NUM2DBL(atpress), NUM2DBL(attemp), NUM2DBL(lapse_rate), NUM2INT(calc_flag), dret);
|
|
1677
|
+
|
|
1678
|
+
VALUE output = rb_ary_new();
|
|
1679
|
+
rb_ary_push(output, rb_float_new(result));
|
|
1680
|
+
for (int i = 0; i < 4; i++)
|
|
1681
|
+
rb_ary_push(output, rb_float_new(dret[i]));
|
|
1682
|
+
return output;
|
|
1683
|
+
}
|
|
1684
|
+
|
|
1685
|
+
/*
|
|
1686
|
+
* Phenomena relevant to heliacal (and other) visibility events.
|
|
1687
|
+
* int32 swe_heliacal_pheno_ut(double tjd_ut, double *geopos, double *datm, double *dobs,
|
|
1688
|
+
* char *ObjectName, int32 TypeEvent, int32 helflag, double *darr, char *serr);
|
|
1689
|
+
* Args: (tjd_ut, object_name, type_event, helflag, lon, lat, height, datm_array, dobs_array)
|
|
1690
|
+
* Returns darr[50]
|
|
1691
|
+
*/
|
|
1692
|
+
static VALUE t_swe_heliacal_pheno_ut(int argc, VALUE *argv, VALUE self)
|
|
1693
|
+
{
|
|
1694
|
+
if (argc != 9)
|
|
1695
|
+
rb_raise(rb_eArgError, "wrong number of arguments (9 required: tjd_ut, object_name, type_event, helflag, lon, lat, height, datm_array, dobs_array)");
|
|
1696
|
+
|
|
1697
|
+
char serr[AS_MAXCH];
|
|
1698
|
+
double geopos[3];
|
|
1699
|
+
geopos[0] = NUM2DBL(argv[4]); // lon
|
|
1700
|
+
geopos[1] = NUM2DBL(argv[5]); // lat
|
|
1701
|
+
geopos[2] = NUM2DBL(argv[6]); // height
|
|
1702
|
+
|
|
1703
|
+
VALUE datm_arr = argv[7];
|
|
1704
|
+
if (TYPE(datm_arr) != T_ARRAY || RARRAY_LEN(datm_arr) < 4)
|
|
1705
|
+
rb_raise(rb_eArgError, "datm must be array of 4 values [pressure, temp, humidity, extinction_coeff]");
|
|
1706
|
+
double datm[4];
|
|
1707
|
+
for (int i = 0; i < 4; i++)
|
|
1708
|
+
datm[i] = NUM2DBL(rb_ary_entry(datm_arr, i));
|
|
1709
|
+
|
|
1710
|
+
VALUE dobs_arr = argv[8];
|
|
1711
|
+
if (TYPE(dobs_arr) != T_ARRAY || RARRAY_LEN(dobs_arr) < 6)
|
|
1712
|
+
rb_raise(rb_eArgError, "dobs must be array of 6 values [age, snellen_left, snellen_right, telescope_mag, telescope_diam, binoc_factor]");
|
|
1713
|
+
double dobs[6];
|
|
1714
|
+
for (int i = 0; i < 6; i++)
|
|
1715
|
+
dobs[i] = NUM2DBL(rb_ary_entry(dobs_arr, i));
|
|
1716
|
+
|
|
1717
|
+
double darr[50];
|
|
1718
|
+
char *object_name = StringValuePtr(argv[1]);
|
|
1719
|
+
|
|
1720
|
+
if (swe_heliacal_pheno_ut(NUM2DBL(argv[0]), geopos, datm, dobs, object_name, NUM2INT(argv[2]), NUM2INT(argv[3]), darr, serr) < 0)
|
|
1721
|
+
rb_raise(rb_eRuntimeError, "%s", serr);
|
|
1722
|
+
|
|
1723
|
+
VALUE output = rb_ary_new();
|
|
1724
|
+
for (int i = 0; i < 50; i++)
|
|
1725
|
+
rb_ary_push(output, rb_float_new(darr[i]));
|
|
1726
|
+
return output;
|
|
1727
|
+
}
|
|
1728
|
+
|
|
1729
|
+
/*
|
|
1730
|
+
* Compute the angle (arcus visionis, and object/sun altitudes) at which an object
|
|
1731
|
+
* of given magnitude becomes heliacally visible.
|
|
1732
|
+
* int32 swe_heliacal_angle(double tjdut, double *dgeo, double *datm, double *dobs, int32 helflag,
|
|
1733
|
+
* double mag, double azi_obj, double azi_sun, double azi_moon, double alt_moon, double *dret, char *serr);
|
|
1734
|
+
* Args: (tjdut, helflag, mag, azi_obj, azi_sun, azi_moon, alt_moon, lon, lat, height, datm_array, dobs_array)
|
|
1735
|
+
* Returns dret[3]: [0] topocentric arcus visionis, [1] object altitude, [2] sun altitude
|
|
1736
|
+
*/
|
|
1737
|
+
static VALUE t_swe_heliacal_angle(int argc, VALUE *argv, VALUE self)
|
|
1738
|
+
{
|
|
1739
|
+
if (argc != 12)
|
|
1740
|
+
rb_raise(rb_eArgError, "wrong number of arguments (12 required: tjdut, helflag, mag, azi_obj, azi_sun, azi_moon, alt_moon, lon, lat, height, datm_array, dobs_array)");
|
|
1741
|
+
|
|
1742
|
+
char serr[AS_MAXCH];
|
|
1743
|
+
double dgeo[3];
|
|
1744
|
+
dgeo[0] = NUM2DBL(argv[7]); // lon
|
|
1745
|
+
dgeo[1] = NUM2DBL(argv[8]); // lat
|
|
1746
|
+
dgeo[2] = NUM2DBL(argv[9]); // height
|
|
1747
|
+
|
|
1748
|
+
VALUE datm_arr = argv[10];
|
|
1749
|
+
if (TYPE(datm_arr) != T_ARRAY || RARRAY_LEN(datm_arr) < 4)
|
|
1750
|
+
rb_raise(rb_eArgError, "datm must be array of 4 values [pressure, temp, humidity, extinction_coeff]");
|
|
1751
|
+
double datm[4];
|
|
1752
|
+
for (int i = 0; i < 4; i++)
|
|
1753
|
+
datm[i] = NUM2DBL(rb_ary_entry(datm_arr, i));
|
|
1754
|
+
|
|
1755
|
+
VALUE dobs_arr = argv[11];
|
|
1756
|
+
if (TYPE(dobs_arr) != T_ARRAY || RARRAY_LEN(dobs_arr) < 6)
|
|
1757
|
+
rb_raise(rb_eArgError, "dobs must be array of 6 values [age, snellen_left, snellen_right, telescope_mag, telescope_diam, binoc_factor]");
|
|
1758
|
+
double dobs[6];
|
|
1759
|
+
for (int i = 0; i < 6; i++)
|
|
1760
|
+
dobs[i] = NUM2DBL(rb_ary_entry(dobs_arr, i));
|
|
1761
|
+
|
|
1762
|
+
double dret[20];
|
|
1763
|
+
if (swe_heliacal_angle(NUM2DBL(argv[0]), dgeo, datm, dobs, NUM2INT(argv[1]),
|
|
1764
|
+
NUM2DBL(argv[2]), NUM2DBL(argv[3]), NUM2DBL(argv[4]), NUM2DBL(argv[5]), NUM2DBL(argv[6]), dret, serr) < 0)
|
|
1765
|
+
rb_raise(rb_eRuntimeError, "%s", serr);
|
|
1766
|
+
|
|
1767
|
+
VALUE output = rb_ary_new();
|
|
1768
|
+
for (int i = 0; i < 3; i++)
|
|
1769
|
+
rb_ary_push(output, rb_float_new(dret[i]));
|
|
1770
|
+
return output;
|
|
1771
|
+
}
|
|
1772
|
+
|
|
1773
|
+
/*
|
|
1774
|
+
* Compute the topocentric arcus visionis for an object of given magnitude and geometry.
|
|
1775
|
+
* int32 swe_topo_arcus_visionis(double tjdut, double *dgeo, double *datm, double *dobs, int32 helflag,
|
|
1776
|
+
* double mag, double azi_obj, double alt_obj, double azi_sun, double azi_moon, double alt_moon, double *dret, char *serr);
|
|
1777
|
+
* Args: (tjdut, helflag, mag, azi_obj, alt_obj, azi_sun, azi_moon, alt_moon, lon, lat, height, datm_array, dobs_array)
|
|
1778
|
+
* Returns dret[1]: topocentric arcus visionis in degrees
|
|
1779
|
+
*/
|
|
1780
|
+
static VALUE t_swe_topo_arcus_visionis(int argc, VALUE *argv, VALUE self)
|
|
1781
|
+
{
|
|
1782
|
+
if (argc != 13)
|
|
1783
|
+
rb_raise(rb_eArgError, "wrong number of arguments (13 required: tjdut, helflag, mag, azi_obj, alt_obj, azi_sun, azi_moon, alt_moon, lon, lat, height, datm_array, dobs_array)");
|
|
1784
|
+
|
|
1785
|
+
char serr[AS_MAXCH];
|
|
1786
|
+
double dgeo[3];
|
|
1787
|
+
dgeo[0] = NUM2DBL(argv[8]); // lon
|
|
1788
|
+
dgeo[1] = NUM2DBL(argv[9]); // lat
|
|
1789
|
+
dgeo[2] = NUM2DBL(argv[10]); // height
|
|
1790
|
+
|
|
1791
|
+
VALUE datm_arr = argv[11];
|
|
1792
|
+
if (TYPE(datm_arr) != T_ARRAY || RARRAY_LEN(datm_arr) < 4)
|
|
1793
|
+
rb_raise(rb_eArgError, "datm must be array of 4 values [pressure, temp, humidity, extinction_coeff]");
|
|
1794
|
+
double datm[4];
|
|
1795
|
+
for (int i = 0; i < 4; i++)
|
|
1796
|
+
datm[i] = NUM2DBL(rb_ary_entry(datm_arr, i));
|
|
1797
|
+
|
|
1798
|
+
VALUE dobs_arr = argv[12];
|
|
1799
|
+
if (TYPE(dobs_arr) != T_ARRAY || RARRAY_LEN(dobs_arr) < 6)
|
|
1800
|
+
rb_raise(rb_eArgError, "dobs must be array of 6 values [age, snellen_left, snellen_right, telescope_mag, telescope_diam, binoc_factor]");
|
|
1801
|
+
double dobs[6];
|
|
1802
|
+
for (int i = 0; i < 6; i++)
|
|
1803
|
+
dobs[i] = NUM2DBL(rb_ary_entry(dobs_arr, i));
|
|
1804
|
+
|
|
1805
|
+
double dret[20];
|
|
1806
|
+
if (swe_topo_arcus_visionis(NUM2DBL(argv[0]), dgeo, datm, dobs, NUM2INT(argv[1]),
|
|
1807
|
+
NUM2DBL(argv[2]), NUM2DBL(argv[3]), NUM2DBL(argv[4]), NUM2DBL(argv[5]), NUM2DBL(argv[6]), NUM2DBL(argv[7]), dret, serr) < 0)
|
|
1808
|
+
rb_raise(rb_eRuntimeError, "%s", serr);
|
|
1809
|
+
|
|
1810
|
+
VALUE output = rb_ary_new();
|
|
1811
|
+
rb_ary_push(output, rb_float_new(dret[0]));
|
|
1812
|
+
return output;
|
|
1813
|
+
}
|
|
1814
|
+
|
|
1815
|
+
/*
|
|
1816
|
+
* Find geographic location where an occultation of a body by the Moon is
|
|
1817
|
+
* central (or maximal) at a given tjd. This is the occultation analogue of
|
|
1818
|
+
* swe_sol_eclipse_where (a solar eclipse is the Moon occulting the Sun).
|
|
1819
|
+
* int32 swe_lun_occult_where(double tjd, int32 ipl, char *starname, int32 ifl, double *geopos, double *attr, char *serr);
|
|
1820
|
+
* ipl: planet number of the occulted body (ignored when starname is given)
|
|
1821
|
+
* starname: fixed-star name, or nil / "" to occult the planet in ipl
|
|
1822
|
+
* Returns [type, geopos[2], attr[20]]
|
|
1823
|
+
*/
|
|
1824
|
+
static VALUE t_swe_lun_occult_where(VALUE self, VALUE tjd, VALUE ipl, VALUE starname, VALUE ifl)
|
|
1825
|
+
{
|
|
1826
|
+
char serr[AS_MAXCH];
|
|
1827
|
+
char star[AS_MAXCH];
|
|
1828
|
+
double geopos[10];
|
|
1829
|
+
double attr[20];
|
|
1830
|
+
|
|
1831
|
+
if (NIL_P(starname))
|
|
1832
|
+
star[0] = '\0';
|
|
1833
|
+
else {
|
|
1834
|
+
strncpy(star, StringValueCStr(starname), AS_MAXCH - 1);
|
|
1835
|
+
star[AS_MAXCH - 1] = '\0';
|
|
1836
|
+
}
|
|
1837
|
+
|
|
1838
|
+
int32 result = swe_lun_occult_where(NUM2DBL(tjd), NUM2INT(ipl), star, NUM2INT(ifl), geopos, attr, serr);
|
|
1839
|
+
if (result < 0)
|
|
1840
|
+
rb_raise(rb_eRuntimeError, "%s", serr);
|
|
1841
|
+
|
|
1842
|
+
VALUE output = rb_ary_new();
|
|
1843
|
+
rb_ary_push(output, INT2NUM(result)); // eclipse type flags
|
|
1844
|
+
|
|
1845
|
+
VALUE _geopos = rb_ary_new();
|
|
1846
|
+
rb_ary_push(_geopos, rb_float_new(geopos[0])); // longitude
|
|
1847
|
+
rb_ary_push(_geopos, rb_float_new(geopos[1])); // latitude
|
|
1848
|
+
rb_ary_push(output, _geopos);
|
|
1849
|
+
|
|
1850
|
+
VALUE _attr = rb_ary_new();
|
|
1851
|
+
for (int i = 0; i < 20; i++)
|
|
1852
|
+
rb_ary_push(_attr, rb_float_new(attr[i]));
|
|
1853
|
+
rb_ary_push(output, _attr);
|
|
1854
|
+
|
|
1855
|
+
return output;
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1858
|
+
/*
|
|
1859
|
+
* Find the time of the next (or previous) occultation of a body by the Moon
|
|
1860
|
+
* visible from a given location. Occultation analogue of swe_sol_eclipse_when_loc.
|
|
1861
|
+
* int32 swe_lun_occult_when_loc(double tjd_start, int32 ipl, char *starname, int32 ifl,
|
|
1862
|
+
* double *geopos, double *tret, double *attr, int32 backward, char *serr);
|
|
1863
|
+
* starname: fixed-star name, or nil / "" to occult the planet in ipl
|
|
1864
|
+
* Returns [type, tret[10], attr[20]]
|
|
1865
|
+
*/
|
|
1866
|
+
static VALUE t_swe_lun_occult_when_loc(VALUE self, VALUE tjd_start, VALUE ipl, VALUE starname, VALUE ifl, VALUE lon, VALUE lat, VALUE height, VALUE backward)
|
|
1867
|
+
{
|
|
1868
|
+
char serr[AS_MAXCH];
|
|
1869
|
+
char star[AS_MAXCH];
|
|
1870
|
+
double geopos[3];
|
|
1871
|
+
double tret[10];
|
|
1872
|
+
double attr[20];
|
|
1873
|
+
|
|
1874
|
+
geopos[0] = NUM2DBL(lon);
|
|
1875
|
+
geopos[1] = NUM2DBL(lat);
|
|
1876
|
+
geopos[2] = NUM2DBL(height);
|
|
1877
|
+
|
|
1878
|
+
if (NIL_P(starname))
|
|
1879
|
+
star[0] = '\0';
|
|
1880
|
+
else {
|
|
1881
|
+
strncpy(star, StringValueCStr(starname), AS_MAXCH - 1);
|
|
1882
|
+
star[AS_MAXCH - 1] = '\0';
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1885
|
+
int32 result = swe_lun_occult_when_loc(NUM2DBL(tjd_start), NUM2INT(ipl), star, NUM2INT(ifl), geopos, tret, attr, NUM2INT(backward), serr);
|
|
1886
|
+
if (result < 0)
|
|
1887
|
+
rb_raise(rb_eRuntimeError, "%s", serr);
|
|
1888
|
+
|
|
1889
|
+
VALUE output = rb_ary_new();
|
|
1890
|
+
rb_ary_push(output, INT2NUM(result)); // eclipse type flags
|
|
1891
|
+
|
|
1892
|
+
VALUE _tret = rb_ary_new();
|
|
1893
|
+
for (int i = 0; i < 10; i++)
|
|
1894
|
+
rb_ary_push(_tret, rb_float_new(tret[i]));
|
|
1895
|
+
rb_ary_push(output, _tret);
|
|
1896
|
+
|
|
1897
|
+
VALUE _attr = rb_ary_new();
|
|
1898
|
+
for (int i = 0; i < 20; i++)
|
|
1899
|
+
rb_ary_push(_attr, rb_float_new(attr[i]));
|
|
1900
|
+
rb_ary_push(output, _attr);
|
|
1901
|
+
|
|
1902
|
+
return output;
|
|
1903
|
+
}
|
|
1904
|
+
|
|
1905
|
+
/*
|
|
1906
|
+
* Find the time of the next (or previous) occultation of a body by the Moon
|
|
1907
|
+
* anywhere on Earth. Occultation analogue of swe_sol_eclipse_when_glob.
|
|
1908
|
+
* int32 swe_lun_occult_when_glob(double tjd_start, int32 ipl, char *starname, int32 ifl, int32 ifltype,
|
|
1909
|
+
* double *tret, int32 backward, char *serr);
|
|
1910
|
+
* ifltype: SE_ECL_TOTAL, SE_ECL_ANNULAR, SE_ECL_PARTIAL, SE_ECL_CENTRAL, SE_ECL_NONCENTRAL, or 0 for any
|
|
1911
|
+
* starname: fixed-star name, or nil / "" to occult the planet in ipl
|
|
1912
|
+
* Returns [type, tret[10]]
|
|
1913
|
+
*/
|
|
1914
|
+
static VALUE t_swe_lun_occult_when_glob(VALUE self, VALUE tjd_start, VALUE ipl, VALUE starname, VALUE ifl, VALUE ifltype, VALUE backward)
|
|
1915
|
+
{
|
|
1916
|
+
char serr[AS_MAXCH];
|
|
1917
|
+
char star[AS_MAXCH];
|
|
1918
|
+
double tret[10];
|
|
1919
|
+
|
|
1920
|
+
if (NIL_P(starname))
|
|
1921
|
+
star[0] = '\0';
|
|
1922
|
+
else {
|
|
1923
|
+
strncpy(star, StringValueCStr(starname), AS_MAXCH - 1);
|
|
1924
|
+
star[AS_MAXCH - 1] = '\0';
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1927
|
+
int32 result = swe_lun_occult_when_glob(NUM2DBL(tjd_start), NUM2INT(ipl), star, NUM2INT(ifl), NUM2INT(ifltype), tret, NUM2INT(backward), serr);
|
|
1928
|
+
if (result < 0)
|
|
1929
|
+
rb_raise(rb_eRuntimeError, "%s", serr);
|
|
1930
|
+
|
|
1931
|
+
VALUE output = rb_ary_new();
|
|
1932
|
+
rb_ary_push(output, INT2NUM(result)); // eclipse type flags
|
|
1933
|
+
for (int i = 0; i < 10; i++)
|
|
1934
|
+
rb_ary_push(output, rb_float_new(tret[i]));
|
|
1935
|
+
return output;
|
|
1936
|
+
}
|
|
1937
|
+
|
|
1663
1938
|
void Init_swisseph()
|
|
1664
1939
|
{
|
|
1665
1940
|
// Module
|
|
@@ -1698,6 +1973,7 @@ void Init_swisseph()
|
|
|
1698
1973
|
rb_define_module_function(rb_mSwisseph, "swe_azalt", t_swe_azalt, 10);
|
|
1699
1974
|
rb_define_module_function(rb_mSwisseph, "swe_azalt_rev", t_swe_azalt_rev, 7);
|
|
1700
1975
|
rb_define_module_function(rb_mSwisseph, "swe_refrac", t_swe_refrac, 4);
|
|
1976
|
+
rb_define_module_function(rb_mSwisseph, "swe_refrac_extended", t_swe_refrac_extended, 6);
|
|
1701
1977
|
rb_define_module_function(rb_mSwisseph, "swe_pheno_ut", t_swe_pheno_ut, 3);
|
|
1702
1978
|
rb_define_module_function(rb_mSwisseph, "swe_time_equ", t_swe_time_equ, 1);
|
|
1703
1979
|
rb_define_module_function(rb_mSwisseph, "swe_lmt_to_lat", t_swe_lmt_to_lat, 2);
|
|
@@ -1726,9 +2002,15 @@ void Init_swisseph()
|
|
|
1726
2002
|
rb_define_module_function(rb_mSwisseph, "swe_lun_eclipse_when", t_swe_lun_eclipse_when, 4);
|
|
1727
2003
|
rb_define_module_function(rb_mSwisseph, "swe_lun_eclipse_when_loc", t_swe_lun_eclipse_when_loc, 6);
|
|
1728
2004
|
rb_define_module_function(rb_mSwisseph, "swe_lun_eclipse_how", t_swe_lun_eclipse_how, 5);
|
|
2005
|
+
rb_define_module_function(rb_mSwisseph, "swe_lun_occult_where", t_swe_lun_occult_where, 4);
|
|
2006
|
+
rb_define_module_function(rb_mSwisseph, "swe_lun_occult_when_loc", t_swe_lun_occult_when_loc, 8);
|
|
2007
|
+
rb_define_module_function(rb_mSwisseph, "swe_lun_occult_when_glob", t_swe_lun_occult_when_glob, 6);
|
|
1729
2008
|
rb_define_module_function(rb_mSwisseph, "swe_gauquelin_sector", t_swe_gauquelin_sector, 9);
|
|
1730
2009
|
rb_define_module_function(rb_mSwisseph, "swe_heliacal_ut", t_swe_heliacal_ut, -1);
|
|
1731
2010
|
rb_define_module_function(rb_mSwisseph, "swe_vis_limit_mag", t_swe_vis_limit_mag, -1);
|
|
2011
|
+
rb_define_module_function(rb_mSwisseph, "swe_heliacal_pheno_ut", t_swe_heliacal_pheno_ut, -1);
|
|
2012
|
+
rb_define_module_function(rb_mSwisseph, "swe_heliacal_angle", t_swe_heliacal_angle, -1);
|
|
2013
|
+
rb_define_module_function(rb_mSwisseph, "swe_topo_arcus_visionis", t_swe_topo_arcus_visionis, -1);
|
|
1732
2014
|
|
|
1733
2015
|
// ET (Ephemeris Time) versions
|
|
1734
2016
|
rb_define_module_function(rb_mSwisseph, "swe_calc", t_swe_calc, 3);
|
data/lib/swisseph.rb
CHANGED
|
@@ -17,26 +17,39 @@ module Swisseph
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
module Swisseph
|
|
20
|
-
# The Swiss Ephemeris C library
|
|
21
|
-
#
|
|
22
|
-
# threads
|
|
23
|
-
# call is serialized through
|
|
24
|
-
#
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
-
#
|
|
20
|
+
# The Swiss Ephemeris C library keeps its mutable state in one `struct swe_data
|
|
21
|
+
# swed`. On a build where `swed` is a plain process global it is NOT thread-safe:
|
|
22
|
+
# two threads inside the C library at once can segfault the process, so every
|
|
23
|
+
# native call is serialized through this global re-entrant lock.
|
|
24
|
+
#
|
|
25
|
+
# BUT libswe declares `swed` with the `TLS` macro (sweodef.h). On any build where
|
|
26
|
+
# TLS resolves to real thread-local storage (`__thread` / `_Thread_local` /
|
|
27
|
+
# `__declspec(thread)`) each thread gets its own `swed` -- own file descriptors,
|
|
28
|
+
# own caches -- and the library is genuinely per-thread reentrant. That is the
|
|
29
|
+
# case on Linux, and on macOS with the extconf.rb patch that drops the legacy
|
|
30
|
+
# `__APPLE__` exclusion (modern clang supports __thread). On such a build the
|
|
31
|
+
# lock is pure overhead: it serializes ephemeris work that could run in parallel.
|
|
28
32
|
LOCK = Monitor.new
|
|
33
|
+
|
|
34
|
+
# Serialize native calls through LOCK unless explicitly disabled. Set
|
|
35
|
+
# SWISSEPH_NOLOCK=1 ONLY on a thread-local (TLS) build -- disabling the lock on a
|
|
36
|
+
# non-TLS build will segfault under concurrency. Reentrancy verified 2026-08-19
|
|
37
|
+
# under ThreadSanitizer (12 threads, no lock, zero data races, exact values).
|
|
38
|
+
LOCKING = ENV['SWISSEPH_NOLOCK'] != '1'
|
|
29
39
|
end
|
|
30
40
|
|
|
31
|
-
# Wrap every current singleton method (the native swe_* methods and the
|
|
32
|
-
#
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
41
|
+
# Wrap every current singleton method (the native swe_* methods and the shorthand
|
|
42
|
+
# aliases defined above) so each public entry point takes the lock -- unless
|
|
43
|
+
# locking is disabled, in which case the native methods are called directly.
|
|
44
|
+
if Swisseph::LOCKING
|
|
45
|
+
Swisseph.singleton_class.prepend(
|
|
46
|
+
Module.new do
|
|
47
|
+
lock = Swisseph::LOCK
|
|
48
|
+
Swisseph.singleton_methods(false).each do |name|
|
|
49
|
+
define_method(name) do |*args, &block|
|
|
50
|
+
lock.synchronize { super(*args, &block) }
|
|
51
|
+
end
|
|
39
52
|
end
|
|
40
53
|
end
|
|
41
|
-
|
|
42
|
-
|
|
54
|
+
)
|
|
55
|
+
end
|