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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
//
// A rust binding for the GSL library by Guillaume Gomez (guillaume1.gomez@gmail.com)
//

/*!
The routines described in this section compute the angular and radial Mathieu functions, and their characteristic values. Mathieu functions are the solutions of the following two differential equations:

d^2y/dv^2 + (a - 2q\cos 2v)y = 0

d^2f/du^2 - (a - 2q\cosh 2u)f = 0

The angular Mathieu functions ce_r(x,q), se_r(x,q) are the even and odd periodic solutions of the first equation, which is known as Mathieu’s equation. These exist only for the discrete sequence of characteristic values a=a_r(q) (even-periodic) and a=b_r(q) (odd-periodic).

The radial Mathieu functions Mc^{(j)}_{r}(z,q), Ms^{(j)}_{r}(z,q) are the solutions of the second equation, which is referred to as Mathieu’s modified equation. The radial Mathieu functions of the first, second, third and fourth kind are denoted by the parameter j, which takes the value 1, 2, 3 or 4.

For more information on the Mathieu functions, see Abramowitz and Stegun, Chapter 20.
!*/

use crate::Value;
use ffi::FFI;
use std::mem::MaybeUninit;

ffi_wrapper!(MathieuWorkspace, *mut sys::gsl_sf_mathieu_workspace, gsl_sf_mathieu_free,
"The Mathieu functions can be computed for a single order or for multiple orders, using array-based
routines. The array-based routines require a preallocated workspace.");

impl MathieuWorkspace {
    /// This function returns a workspace for the array versions of the Mathieu routines.
    /// The arguments n and qmax specify the maximum order and q-value of Mathieu functions which can be computed with this workspace.
    #[doc(alias = "gsl_sf_mathieu_alloc")]
    pub fn new(n: usize, qmax: f64) -> Option<MathieuWorkspace> {
        let tmp = unsafe { sys::gsl_sf_mathieu_alloc(n, qmax) };

        if tmp.is_null() {
            None
        } else {
            Some(Self::wrap(tmp))
        }
    }

    /// This routine computes the characteristic values a_n(q), b_n(q) of the Mathieu functions ce_n(q,x) and se_n(q,x), respectively.
    #[doc(alias = "gsl_sf_mathieu_a_e")]
    pub fn mathieu_a(n: i32, q: f64) -> (Value, ::types::Result) {
        let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
        let ret = unsafe { sys::gsl_sf_mathieu_a_e(n, q, result.as_mut_ptr()) };

        (::Value::from(ret), unsafe { result.assume_init() }.into())
    }

    /// This routine computes the characteristic values a_n(q), b_n(q) of the Mathieu functions ce_n(q,x) and se_n(q,x), respectively.
    #[doc(alias = "gsl_sf_mathieu_b_e")]
    pub fn mathieu_b(n: i32, q: f64) -> (Value, ::types::Result) {
        let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
        let ret = unsafe { sys::gsl_sf_mathieu_b_e(n, q, result.as_mut_ptr()) };

        (::Value::from(ret), unsafe { result.assume_init() }.into())
    }

    /// This routine computes a series of Mathieu characteristic values a_n(q), b_n(q) for n from order_min to order_max inclusive, storing the results in the array result_array.
    #[doc(alias = "gsl_sf_mathieu_a_array")]
    pub fn mathieu_a_array(
        &mut self,
        order_min: i32,
        order_max: i32,
        q: f64,
        result_array: &mut [f64],
    ) -> Value {
        Value::from(unsafe {
            sys::gsl_sf_mathieu_a_array(
                order_min,
                order_max,
                q,
                self.unwrap_unique(),
                result_array.as_mut_ptr(),
            )
        })
    }

    /// This routine computes a series of Mathieu characteristic values a_n(q), b_n(q) for n from order_min to order_max inclusive, storing the results in the array result_array.
    #[doc(alias = "gsl_sf_mathieu_b_array")]
    pub fn mathieu_b_array(
        &mut self,
        order_min: i32,
        order_max: i32,
        q: f64,
        result_array: &mut [f64],
    ) -> Value {
        Value::from(unsafe {
            sys::gsl_sf_mathieu_b_array(
                order_min,
                order_max,
                q,
                self.unwrap_unique(),
                result_array.as_mut_ptr(),
            )
        })
    }

    /// This routine computes the angular Mathieu functions ce_n(q,x) and se_n(q,x), respectively.
    #[doc(alias = "gsl_sf_mathieu_ce_e")]
    pub fn mathieu_ce(n: i32, q: f64, x: f64) -> (Value, ::types::Result) {
        let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
        let ret = unsafe { sys::gsl_sf_mathieu_ce_e(n, q, x, result.as_mut_ptr()) };

        (::Value::from(ret), unsafe { result.assume_init() }.into())
    }

    /// This routine computes the angular Mathieu functions ce_n(q,x) and se_n(q,x), respectively.
    #[doc(alias = "gsl_sf_mathieu_se_e")]
    pub fn mathieu_se(n: i32, q: f64, x: f64) -> (Value, ::types::Result) {
        let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
        let ret = unsafe { sys::gsl_sf_mathieu_se_e(n, q, x, result.as_mut_ptr()) };

        (::Value::from(ret), unsafe { result.assume_init() }.into())
    }

    /// This routine computes a series of the angular Mathieu functions ce_n(q,x) and se_n(q,x) of order n from nmin to nmax inclusive, storing the results in the array result_array.
    #[doc(alias = "gsl_sf_mathieu_ce_array")]
    pub fn mathieu_ce_array(
        &mut self,
        nmin: i32,
        nmax: i32,
        q: f64,
        x: f64,
        result_array: &mut [f64],
    ) -> Value {
        Value::from(unsafe {
            sys::gsl_sf_mathieu_ce_array(
                nmin,
                nmax,
                q,
                x,
                self.unwrap_unique(),
                result_array.as_mut_ptr(),
            )
        })
    }

    /// This routine computes a series of the angular Mathieu functions ce_n(q,x) and se_n(q,x) of order n from nmin to nmax inclusive, storing the results in the array result_array.
    #[doc(alias = "gsl_sf_mathieu_se_array")]
    pub fn mathieu_se_array(
        &mut self,
        nmin: i32,
        nmax: i32,
        q: f64,
        x: f64,
        result_array: &mut [f64],
    ) -> Value {
        Value::from(unsafe {
            sys::gsl_sf_mathieu_se_array(
                nmin,
                nmax,
                q,
                x,
                self.unwrap_unique(),
                result_array.as_mut_ptr(),
            )
        })
    }

    /// This routine computes the radial j-th kind Mathieu functions Mc_n^{(j)}(q,x) and Ms_n^{(j)}(q,x) of order n.
    ///
    /// The allowed values of j are 1 and 2. The functions for j = 3,4 can be computed as M_n^{(3)} = M_n^{(1)} + iM_n^{(2)} and M_n^{(4)} = M_n^{(1)} - iM_n^{(2)}, where M_n^{(j)} = Mc_n^{(j)} or Ms_n^{(j)}.
    #[doc(alias = "gsl_sf_mathieu_Mc_e")]
    pub fn mathieu_Mc(j: i32, n: i32, q: f64, x: f64) -> (Value, ::types::Result) {
        let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
        let ret = unsafe { sys::gsl_sf_mathieu_Mc_e(j, n, q, x, result.as_mut_ptr()) };

        (::Value::from(ret), unsafe { result.assume_init() }.into())
    }

    /// This routine computes the radial j-th kind Mathieu functions Mc_n^{(j)}(q,x) and Ms_n^{(j)}(q,x) of order n.
    ///
    /// The allowed values of j are 1 and 2. The functions for j = 3,4 can be computed as M_n^{(3)} = M_n^{(1)} + iM_n^{(2)} and M_n^{(4)} = M_n^{(1)} - iM_n^{(2)}, where M_n^{(j)} = Mc_n^{(j)} or Ms_n^{(j)}.
    #[doc(alias = "gsl_sf_mathieu_Ms_e")]
    pub fn mathieu_Ms(j: i32, n: i32, q: f64, x: f64) -> (Value, ::types::Result) {
        let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
        let ret = unsafe { sys::gsl_sf_mathieu_Ms_e(j, n, q, x, result.as_mut_ptr()) };

        (::Value::from(ret), unsafe { result.assume_init() }.into())
    }

    /// This routine computes a series of the radial Mathieu functions of kind j, with order from nmin to nmax inclusive, storing the results in the array result_array.
    #[doc(alias = "gsl_sf_mathieu_Mc_array")]
    pub fn mathieu_Mc_array(
        &mut self,
        j: i32,
        nmin: i32,
        nmax: i32,
        q: f64,
        x: f64,
        result_array: &mut [f64],
    ) -> Value {
        Value::from(unsafe {
            sys::gsl_sf_mathieu_Mc_array(
                j,
                nmin,
                nmax,
                q,
                x,
                self.unwrap_unique(),
                result_array.as_mut_ptr(),
            )
        })
    }

    /// This routine computes a series of the radial Mathieu functions of kind j, with order from nmin to nmax inclusive, storing the results in the array result_array.
    #[doc(alias = "gsl_sf_mathieu_Ms_array")]
    pub fn mathieu_Ms_array(
        &mut self,
        j: i32,
        nmin: i32,
        nmax: i32,
        q: f64,
        x: f64,
        result_array: &mut [f64],
    ) -> Value {
        Value::from(unsafe {
            sys::gsl_sf_mathieu_Ms_array(
                j,
                nmin,
                nmax,
                q,
                x,
                self.unwrap_unique(),
                result_array.as_mut_ptr(),
            )
        })
    }
}