1 /*============================================================================
2   WCSLIB 7.7 - an implementation of the FITS WCS standard.
3   Copyright (C) 1995-2021, Mark Calabretta
4 
5   This file is part of WCSLIB.
6 
7   WCSLIB is free software: you can redistribute it and/or modify it under the
8   terms of the GNU Lesser General Public License as published by the Free
9   Software Foundation, either version 3 of the License, or (at your option)
10   any later version.
11 
12   WCSLIB is distributed in the hope that it will be useful, but WITHOUT ANY
13   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14   FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
15   more details.
16 
17   You should have received a copy of the GNU Lesser General Public License
18   along with WCSLIB.  If not, see http://www.gnu.org/licenses.
19 
20   Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
21   http://www.atnf.csiro.au/people/Mark.Calabretta
22   $Id: spx.c,v 7.7 2021/07/12 06:36:49 mcalabre Exp $
23 *===========================================================================*/
24 
25 #include <math.h>
26 #include <stdio.h>
27 #include <string.h>
28 
29 #include "wcserr.h"
30 #include "wcsmath.h"
31 #include "spx.h"
32 
33 
34 // Map status return value to message.
35 const char *spx_errmsg[] = {
36   "Success",
37   "Null spxprm pointer passed",
38   "Invalid spectral parameters",
39   "Invalid spectral variable",
40   "One or more of the inspec coordinates were invalid"};
41 
42 // Convenience macro for invoking wcserr_set().
43 #define SPX_ERRMSG(status) WCSERR_SET(status), spx_errmsg[status]
44 
45 #define C 2.99792458e8
46 #define h 6.6260755e-34
47 
48 /*============================================================================
49 *   Spectral cross conversions; given one spectral coordinate it computes all
50 *   the others, plus the required derivatives of each with respect to the
51 *   others.
52 *===========================================================================*/
53 
specx(const char * type,double spec,double restfrq,double restwav,struct spxprm * spx)54 int specx(
55   const char *type,
56   double spec,
57   double restfrq,
58   double restwav,
59   struct spxprm *spx)
60 
61 {
62   static const char *function = "specx";
63 
64   register int k;
65   int haverest;
66   double beta, dwaveawav, gamma, n, s, t, u;
67   struct wcserr **err;
68 
69   if (spx == 0x0) return SPXERR_NULL_POINTER;
70   err = &(spx->err);
71 
72   haverest = 1;
73   if (restfrq == 0.0) {
74     if (restwav == 0.0) {
75       // No line rest frequency supplied.
76       haverest = 0;
77 
78       // Temporarily set a dummy value for conversions.
79       spx->restwav = 1.0;
80     } else {
81       spx->restwav = restwav;
82     }
83     spx->restfrq = C/spx->restwav;
84 
85   } else {
86     spx->restfrq = restfrq;
87     spx->restwav = C/restfrq;
88   }
89 
90   spx->err = 0x0;
91 
92   // Convert to frequency.
93   spx->wavetype = 0;
94   spx->velotype = 0;
95   if (strcmp(type, "FREQ") == 0) {
96     if (spec == 0.0) {
97       return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
98         "Invalid spectral variable: frequency == 0");
99     }
100     spx->freq = spec;
101     spx->wavetype = 1;
102 
103   } else if (strcmp(type, "AFRQ") == 0) {
104     if (spec == 0.0) {
105       return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
106         "Invalid spectral variable: frequency == 0");
107     }
108     spx->freq = spec/(2.0*PI);
109     spx->wavetype = 1;
110 
111   } else if (strcmp(type, "ENER") == 0) {
112     if (spec == 0.0) {
113       return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
114         "Invalid spectral variable: frequency == 0");
115     }
116     spx->freq = spec/h;
117     spx->wavetype = 1;
118 
119   } else if (strcmp(type, "WAVN") == 0) {
120     if (spec == 0.0) {
121       return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
122         "Invalid spectral variable: frequency == 0");
123     }
124     spx->freq = spec*C;
125     spx->wavetype = 1;
126 
127   } else if (strcmp(type, "VRAD") == 0) {
128     spx->freq = spx->restfrq*(1.0 - spec/C);
129     spx->velotype = 1;
130 
131   } else if (strcmp(type, "WAVE") == 0) {
132     if (spec == 0.0) {
133       return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
134         "Invalid spectral variable: frequency == 0");
135     }
136     spx->freq = C/spec;
137     spx->wavetype = 1;
138 
139   } else if (strcmp(type, "VOPT") == 0) {
140     s = 1.0 + spec/C;
141     if (s == 0.0) {
142       return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
143         "Invalid spectral variable");
144     }
145     spx->freq = spx->restfrq/s;
146     spx->velotype = 1;
147 
148   } else if (strcmp(type, "ZOPT") == 0) {
149     s = 1.0 + spec;
150     if (s == 0.0) {
151       return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
152         "Invalid spectral variable");
153     }
154     spx->freq = spx->restfrq/s;
155     spx->velotype = 1;
156 
157   } else if (strcmp(type, "AWAV") == 0) {
158     if (spec == 0.0) {
159       return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
160         "Invalid spectral variable");
161     }
162     s = 1.0/spec;
163     s *= s;
164     n  =   2.554e8 / (0.41e14 - s);
165     n += 294.981e8 / (1.46e14 - s);
166     n += 1.000064328;
167     spx->freq = C/(spec*n);
168     spx->wavetype = 1;
169 
170   } else if (strcmp(type, "VELO") == 0) {
171     beta = spec/C;
172     if (fabs(beta) == 1.0) {
173       return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
174         "Invalid spectral variable");
175     }
176     spx->freq = spx->restfrq*(1.0 - beta)/sqrt(1.0 - beta*beta);
177     spx->velotype = 1;
178 
179   } else if (strcmp(type, "BETA") == 0) {
180     if (fabs(spec) == 1.0) {
181       return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
182         "Invalid spectral variable");
183     }
184     spx->freq = spx->restfrq*(1.0 - spec)/sqrt(1.0 - spec*spec);
185     spx->velotype = 1;
186 
187   } else {
188     // Unrecognized type.
189     return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_PARAMS),
190       "Unrecognized spectral type '%s'", type);
191   }
192 
193 
194   // Convert frequency to the other spectral types.
195   n = 1.0;
196   for (k = 0; k < 4; k++) {
197     s = n*spx->freq/C;
198     s *= s;
199     t = 0.41e14 - s;
200     u = 1.46e14 - s;
201     n = 1.000064328 + (2.554e8/t + 294.981e8/u);
202   }
203 
204   dwaveawav = n - 2.0*s*(2.554e8/(t*t) + 294.981e8/(u*u));
205 
206   s = spx->freq/spx->restfrq;
207 
208   spx->ener = spx->freq*h;
209   spx->afrq = spx->freq*(2.0*PI);
210   spx->wavn = spx->freq/C;
211   spx->vrad = C*(1.0 - s);
212   spx->wave = C/spx->freq;
213   spx->awav = spx->wave/n;
214   spx->vopt = C*(1.0/s - 1.0);
215   spx->zopt = spx->vopt/C;
216   spx->velo = C*(1.0 - s*s)/(1.0 + s*s);
217   spx->beta = spx->velo/C;
218 
219   // Compute the required derivatives.
220   gamma = 1.0/sqrt(1.0 - spx->beta*spx->beta);
221 
222   spx->dfreqafrq = 1.0/(2.0*PI);
223   spx->dafrqfreq = 1.0/spx->dfreqafrq;
224 
225   spx->dfreqener = 1.0/h;
226   spx->denerfreq = 1.0/spx->dfreqener;
227 
228   spx->dfreqwavn = C;
229   spx->dwavnfreq = 1.0/spx->dfreqwavn;
230 
231   spx->dfreqvrad = -spx->restfrq/C;
232   spx->dvradfreq = 1.0/spx->dfreqvrad;
233 
234   spx->dfreqwave = -spx->freq/spx->wave;
235   spx->dwavefreq = 1.0/spx->dfreqwave;
236 
237   spx->dfreqawav = spx->dfreqwave * dwaveawav;
238   spx->dawavfreq = 1.0/spx->dfreqawav;
239 
240   spx->dfreqvelo = -gamma*spx->restfrq/(C + spx->velo);
241   spx->dvelofreq = 1.0/spx->dfreqvelo;
242 
243   spx->dwavevopt = spx->restwav/C;
244   spx->dvoptwave = 1.0/spx->dwavevopt;
245 
246   spx->dwavezopt = spx->restwav;
247   spx->dzoptwave = 1.0/spx->dwavezopt;
248 
249   spx->dwaveawav = dwaveawav;
250   spx->dawavwave = 1.0/spx->dwaveawav;
251 
252   spx->dwavevelo = gamma*spx->restwav/(C - spx->velo);
253   spx->dvelowave = 1.0/spx->dwavevelo;
254 
255   spx->dawavvelo = spx->dwavevelo/dwaveawav;
256   spx->dveloawav = 1.0/spx->dawavvelo;
257 
258   spx->dvelobeta = C;
259   spx->dbetavelo = 1.0/spx->dvelobeta;
260 
261 
262   // Reset values if no line rest frequency was supplied.
263   if (haverest) {
264     spx->wavetype = 1;
265     spx->velotype = 1;
266 
267   } else {
268     spx->restfrq = 0.0;
269     spx->restwav = 0.0;
270 
271     if (!spx->wavetype) {
272       // Don't have wave characteristic types.
273       spx->freq = 0.0;
274       spx->afrq = 0.0;
275       spx->ener = 0.0;
276       spx->wavn = 0.0;
277       spx->wave = 0.0;
278       spx->awav = 0.0;
279 
280       spx->dfreqwave = 0.0;
281       spx->dwavefreq = 0.0;
282 
283       spx->dfreqawav = 0.0;
284       spx->dawavfreq = 0.0;
285 
286       spx->dwaveawav = 0.0;
287       spx->dawavwave = 0.0;
288 
289     } else {
290       // Don't have velocity types.
291       spx->vrad = 0.0;
292       spx->vopt = 0.0;
293       spx->zopt = 0.0;
294       spx->velo = 0.0;
295       spx->beta = 0.0;
296     }
297 
298     spx->dfreqvrad = 0.0;
299     spx->dvradfreq = 0.0;
300 
301     spx->dfreqvelo = 0.0;
302     spx->dvelofreq = 0.0;
303 
304     spx->dwavevopt = 0.0;
305     spx->dvoptwave = 0.0;
306 
307     spx->dwavezopt = 0.0;
308     spx->dzoptwave = 0.0;
309 
310     spx->dwavevelo = 0.0;
311     spx->dvelowave = 0.0;
312 
313     spx->dawavvelo = 0.0;
314     spx->dveloawav = 0.0;
315   }
316 
317   return 0;
318 }
319 
320 //----------------------------------------------------------------------------
321 
spxperr(const struct spxprm * spx,const char * prefix)322 int spxperr(const struct spxprm *spx, const char *prefix)
323 
324 {
325   if (spx == 0x0) return SPXERR_NULL_POINTER;
326 
327   if (spx->err) {
328     wcserr_prt(spx->err, prefix);
329   }
330 
331   return 0;
332 }
333 
334 
335 /*============================================================================
336 *   Conversions between frequency and vacuum wavelength.
337 *===========================================================================*/
338 
freqwave(double dummy,int nfreq,int sfreq,int swave,const double freq[],double wave[],int stat[])339 int freqwave(
340   double dummy,
341   int nfreq,
342   int sfreq,
343   int swave,
344   const double freq[],
345   double wave[],
346   int stat[])
347 
348 {
349   int status = 0;
350   register int ifreq, *statp;
351   register const double *freqp;
352   register double *wavep;
353 
354   // Avert nuisance compiler warnings about unused parameters.
355   (void)dummy;
356 
357   freqp = freq;
358   wavep = wave;
359   statp = stat;
360   for (ifreq = 0; ifreq < nfreq; ifreq++) {
361     if (*freqp != 0.0) {
362       *wavep = C/(*freqp);
363       *(statp++) = 0;
364     } else {
365       *(statp++) = 1;
366       status = SPXERR_BAD_INSPEC_COORD;
367     }
368 
369     freqp += sfreq;
370     wavep += swave;
371   }
372 
373   return status;
374 }
375 
376 //----------------------------------------------------------------------------
377 
wavefreq(double dummy,int nwave,int swave,int sfreq,const double wave[],double freq[],int stat[])378 int wavefreq(
379   double dummy,
380   int nwave,
381   int swave,
382   int sfreq,
383   const double wave[],
384   double freq[],
385   int stat[])
386 
387 {
388   int status = 0;
389   register int iwave, *statp;
390   register const double *wavep;
391   register double *freqp;
392 
393   // Avert nuisance compiler warnings about unused parameters.
394   (void)dummy;
395 
396   wavep = wave;
397   freqp = freq;
398   statp = stat;
399   for (iwave = 0; iwave < nwave; iwave++) {
400     if (*wavep != 0.0) {
401       *freqp = C/(*wavep);
402       *(statp++) = 0;
403     } else {
404       *(statp++) = 1;
405       status = SPXERR_BAD_INSPEC_COORD;
406     }
407 
408     wavep += swave;
409     freqp += sfreq;
410   }
411 
412   return status;
413 }
414 
415 /*============================================================================
416 *   Conversions between frequency and air wavelength.
417 *===========================================================================*/
418 
freqawav(double dummy,int nfreq,int sfreq,int sawav,const double freq[],double awav[],int stat[])419 int freqawav(
420   double dummy,
421   int nfreq,
422   int sfreq,
423   int sawav,
424   const double freq[],
425   double awav[],
426   int stat[])
427 
428 {
429   int status;
430 
431   if ((status = freqwave(dummy, nfreq, sfreq, sawav, freq, awav, stat))) {
432     return status;
433   }
434 
435   return waveawav(dummy, nfreq, sawav, sawav, awav, awav, stat);
436 }
437 
438 //----------------------------------------------------------------------------
439 
awavfreq(double dummy,int nawav,int sawav,int sfreq,const double awav[],double freq[],int stat[])440 int awavfreq(
441   double dummy,
442   int nawav,
443   int sawav,
444   int sfreq,
445   const double awav[],
446   double freq[],
447   int stat[])
448 
449 {
450   int status;
451 
452   if ((status = awavwave(dummy, nawav, sawav, sfreq, awav, freq, stat))) {
453     return status;
454   }
455 
456   return wavefreq(dummy, nawav, sfreq, sfreq, freq, freq, stat);
457 }
458 
459 /*============================================================================
460 *   Conversions between frequency and relativistic velocity.
461 *===========================================================================*/
462 
freqvelo(double restfrq,int nfreq,int sfreq,int svelo,const double freq[],double velo[],int stat[])463 int freqvelo(
464   double restfrq,
465   int nfreq,
466   int sfreq,
467   int svelo,
468   const double freq[],
469   double velo[],
470   int stat[])
471 
472 {
473   double r, s;
474   register int ifreq, *statp;
475   register const double *freqp;
476   register double *velop;
477 
478   r = restfrq*restfrq;
479 
480   freqp = freq;
481   velop = velo;
482   statp = stat;
483   for (ifreq = 0; ifreq < nfreq; ifreq++) {
484     s = *freqp * *freqp;
485     *velop = C*(r - s)/(r + s);
486     *(statp++) = 0;
487 
488     freqp += sfreq;
489     velop += svelo;
490   }
491 
492   return 0;
493 }
494 
495 //----------------------------------------------------------------------------
496 
velofreq(double restfrq,int nvelo,int svelo,int sfreq,const double velo[],double freq[],int stat[])497 int velofreq(
498   double restfrq,
499   int nvelo,
500   int svelo,
501   int sfreq,
502   const double velo[],
503   double freq[],
504   int stat[])
505 
506 {
507   int status = 0;
508   double s;
509   register int ivelo, *statp;
510   register const double *velop;
511   register double *freqp;
512 
513   velop = velo;
514   freqp = freq;
515   statp = stat;
516   for (ivelo = 0; ivelo < nvelo; ivelo++) {
517     s = C + *velop;
518     if (s != 0.0) {
519       *freqp = restfrq*sqrt((C - *velop)/s);
520       *(statp++) = 0;
521     } else {
522       *(statp++) = 1;
523       status = SPXERR_BAD_INSPEC_COORD;
524     }
525 
526     velop += svelo;
527     freqp += sfreq;
528   }
529 
530   return status;
531 }
532 
533 /*============================================================================
534 *   Conversions between vacuum wavelength and air wavelength.
535 *===========================================================================*/
536 
waveawav(double dummy,int nwave,int swave,int sawav,const double wave[],double awav[],int stat[])537 int waveawav(
538   double dummy,
539   int nwave,
540   int swave,
541   int sawav,
542   const double wave[],
543   double awav[],
544   int stat[])
545 
546 {
547   int status = 0;
548   double n, s;
549   register int iwave, k, *statp;
550   register const double *wavep;
551   register double *awavp;
552 
553   // Avert nuisance compiler warnings about unused parameters.
554   (void)dummy;
555 
556   wavep = wave;
557   awavp = awav;
558   statp = stat;
559   for (iwave = 0; iwave < nwave; iwave++) {
560     if (*wavep != 0.0) {
561       n = 1.0;
562       for (k = 0; k < 4; k++) {
563         s  = n/(*wavep);
564         s *= s;
565         n  =   2.554e8 / (0.41e14 - s);
566         n += 294.981e8 / (1.46e14 - s);
567         n += 1.000064328;
568       }
569 
570       *awavp = (*wavep)/n;
571       *(statp++) = 0;
572     } else {
573       *(statp++) = 1;
574       status = SPXERR_BAD_INSPEC_COORD;
575     }
576 
577     wavep += swave;
578     awavp += sawav;
579   }
580 
581   return status;
582 }
583 
584 //----------------------------------------------------------------------------
585 
awavwave(double dummy,int nawav,int sawav,int swave,const double awav[],double wave[],int stat[])586 int awavwave(
587   double dummy,
588   int nawav,
589   int sawav,
590   int swave,
591   const double awav[],
592   double wave[],
593   int stat[])
594 
595 {
596   int status = 0;
597   double n, s;
598   register int iawav, *statp;
599   register const double *awavp;
600   register double *wavep;
601 
602   // Avert nuisance compiler warnings about unused parameters.
603   (void)dummy;
604 
605   awavp = awav;
606   wavep = wave;
607   statp = stat;
608   for (iawav = 0; iawav < nawav; iawav++) {
609     if (*awavp != 0.0) {
610       s = 1.0/(*awavp);
611       s *= s;
612       n  =   2.554e8 / (0.41e14 - s);
613       n += 294.981e8 / (1.46e14 - s);
614       n += 1.000064328;
615       *wavep = (*awavp)*n;
616       *(statp++) = 0;
617     } else {
618       *(statp++) = 1;
619       status = SPXERR_BAD_INSPEC_COORD;
620     }
621 
622     awavp += sawav;
623     wavep += swave;
624   }
625 
626   return status;
627 }
628 
629 /*============================================================================
630 *   Conversions between vacuum wavelength and relativistic velocity.
631 *===========================================================================*/
632 
wavevelo(double restwav,int nwave,int swave,int svelo,const double wave[],double velo[],int stat[])633 int wavevelo(
634   double restwav,
635   int nwave,
636   int swave,
637   int svelo,
638   const double wave[],
639   double velo[],
640   int stat[])
641 
642 {
643   double r, s;
644   register int iwave, *statp;
645   register const double *wavep;
646   register double *velop;
647 
648   r = restwav*restwav;
649 
650   wavep = wave;
651   velop = velo;
652   statp = stat;
653   for (iwave = 0; iwave < nwave; iwave++) {
654     s = *wavep * *wavep;
655     *velop = C*(s - r)/(s + r);
656     *(statp++) = 0;
657 
658     wavep += swave;
659     velop += svelo;
660   }
661 
662   return 0;
663 }
664 
665 //----------------------------------------------------------------------------
666 
velowave(double restwav,int nvelo,int svelo,int swave,const double velo[],double wave[],int stat[])667 int velowave(
668   double restwav,
669   int nvelo,
670   int svelo,
671   int swave,
672   const double velo[],
673   double wave[],
674   int stat[])
675 
676 {
677   int status = 0;
678   double s;
679   register int ivelo, *statp;
680   register const double *velop;
681   register double *wavep;
682 
683   velop = velo;
684   wavep = wave;
685   statp = stat;
686   for (ivelo = 0; ivelo < nvelo; ivelo++) {
687     s = C - *velop;
688     if (s != 0.0) {
689       *wavep = restwav*sqrt((C + *velop)/s);
690       *(statp++) = 0;
691     } else {
692       *(statp++) = 1;
693       status = SPXERR_BAD_INSPEC_COORD;
694     }
695 
696     velop += svelo;
697     wavep += swave;
698   }
699 
700   return status;
701 }
702 
703 /*============================================================================
704 *   Conversions between air wavelength and relativistic velocity.
705 *===========================================================================*/
706 
awavvelo(double dummy,int nawav,int sawav,int svelo,const double awav[],double velo[],int stat[])707 int awavvelo(
708   double dummy,
709   int nawav,
710   int sawav,
711   int svelo,
712   const double awav[],
713   double velo[],
714   int stat[])
715 
716 {
717   int status;
718 
719   if ((status = awavwave(dummy, nawav, sawav, svelo, awav, velo, stat))) {
720     return status;
721   }
722 
723   return wavevelo(dummy, nawav, svelo, svelo, velo, velo, stat);
724 }
725 
726 //----------------------------------------------------------------------------
727 
veloawav(double dummy,int nvelo,int svelo,int sawav,const double velo[],double awav[],int stat[])728 int veloawav(
729   double dummy,
730   int nvelo,
731   int svelo,
732   int sawav,
733   const double velo[],
734   double awav[],
735   int stat[])
736 
737 {
738   int status;
739 
740   if ((status = velowave(dummy, nvelo, svelo, sawav, velo, awav, stat))) {
741     return status;
742   }
743 
744   return waveawav(dummy, nvelo, sawav, sawav, awav, awav, stat);
745 }
746 
747 /*============================================================================
748 *   Conversions between frequency and angular frequency.
749 *===========================================================================*/
750 
freqafrq(double dummy,int nfreq,int sfreq,int safrq,const double freq[],double afrq[],int stat[])751 int freqafrq(
752   double dummy,
753   int nfreq,
754   int sfreq,
755   int safrq,
756   const double freq[],
757   double afrq[],
758   int stat[])
759 
760 {
761   register int ifreq, *statp;
762   register const double *freqp;
763   register double *afrqp;
764 
765   // Avert nuisance compiler warnings about unused parameters.
766   (void)dummy;
767 
768   freqp = freq;
769   afrqp = afrq;
770   statp = stat;
771   for (ifreq = 0; ifreq < nfreq; ifreq++) {
772     *afrqp = (*freqp)*(2.0*PI);
773     *(statp++) = 0;
774 
775     freqp += sfreq;
776     afrqp += safrq;
777   }
778 
779   return 0;
780 }
781 
782 //----------------------------------------------------------------------------
783 
afrqfreq(double dummy,int nafrq,int safrq,int sfreq,const double afrq[],double freq[],int stat[])784 int afrqfreq(
785   double dummy,
786   int nafrq,
787   int safrq,
788   int sfreq,
789   const double afrq[],
790   double freq[],
791   int stat[])
792 
793 {
794   register int iafrq, *statp;
795   register const double *afrqp;
796   register double *freqp;
797 
798   // Avert nuisance compiler warnings about unused parameters.
799   (void)dummy;
800 
801   afrqp = afrq;
802   freqp = freq;
803   statp = stat;
804   for (iafrq = 0; iafrq < nafrq; iafrq++) {
805     *freqp = (*afrqp)/(2.0*PI);
806     *(statp++) = 0;
807 
808     afrqp += safrq;
809     freqp += sfreq;
810   }
811 
812   return 0;
813 }
814 
815 /*============================================================================
816 *   Conversions between frequency and energy.
817 *===========================================================================*/
818 
freqener(double dummy,int nfreq,int sfreq,int sener,const double freq[],double ener[],int stat[])819 int freqener(
820   double dummy,
821   int nfreq,
822   int sfreq,
823   int sener,
824   const double freq[],
825   double ener[],
826   int stat[])
827 
828 {
829   register int ifreq, *statp;
830   register const double *freqp;
831   register double *enerp;
832 
833   // Avert nuisance compiler warnings about unused parameters.
834   (void)dummy;
835 
836   freqp = freq;
837   enerp = ener;
838   statp = stat;
839   for (ifreq = 0; ifreq < nfreq; ifreq++) {
840     *enerp = (*freqp)*h;
841     *(statp++) = 0;
842 
843     freqp += sfreq;
844     enerp += sener;
845   }
846 
847   return 0;
848 }
849 
850 //----------------------------------------------------------------------------
851 
enerfreq(double dummy,int nener,int sener,int sfreq,const double ener[],double freq[],int stat[])852 int enerfreq(
853   double dummy,
854   int nener,
855   int sener,
856   int sfreq,
857   const double ener[],
858   double freq[],
859   int stat[])
860 
861 {
862   register int iener, *statp;
863   register const double *enerp;
864   register double *freqp;
865 
866   // Avert nuisance compiler warnings about unused parameters.
867   (void)dummy;
868 
869   enerp = ener;
870   freqp = freq;
871   statp = stat;
872   for (iener = 0; iener < nener; iener++) {
873     *freqp = (*enerp)/h;
874     *(statp++) = 0;
875 
876     enerp += sener;
877     freqp += sfreq;
878   }
879 
880   return 0;
881 }
882 
883 /*============================================================================
884 *   Conversions between frequency and wave number.
885 *===========================================================================*/
886 
freqwavn(double dummy,int nfreq,int sfreq,int swavn,const double freq[],double wavn[],int stat[])887 int freqwavn(
888   double dummy,
889   int nfreq,
890   int sfreq,
891   int swavn,
892   const double freq[],
893   double wavn[],
894   int stat[])
895 
896 {
897   register int ifreq, *statp;
898   register const double *freqp;
899   register double *wavnp;
900 
901   // Avert nuisance compiler warnings about unused parameters.
902   (void)dummy;
903 
904   freqp = freq;
905   wavnp = wavn;
906   statp = stat;
907   for (ifreq = 0; ifreq < nfreq; ifreq++) {
908     *wavnp = (*freqp)/C;
909     *(statp++) = 0;
910 
911     freqp += sfreq;
912     wavnp += swavn;
913   }
914 
915   return 0;
916 }
917 
918 //----------------------------------------------------------------------------
919 
wavnfreq(double dummy,int nwavn,int swavn,int sfreq,const double wavn[],double freq[],int stat[])920 int wavnfreq(
921   double dummy,
922   int nwavn,
923   int swavn,
924   int sfreq,
925   const double wavn[],
926   double freq[],
927   int stat[])
928 
929 {
930   register int iwavn, *statp;
931   register const double *wavnp;
932   register double *freqp;
933 
934   // Avert nuisance compiler warnings about unused parameters.
935   (void)dummy;
936 
937   wavnp = wavn;
938   freqp = freq;
939   statp = stat;
940   for (iwavn = 0; iwavn < nwavn; iwavn++) {
941     *freqp = (*wavnp)*C;
942     *(statp++) = 0;
943 
944     wavnp += swavn;
945     freqp += sfreq;
946   }
947 
948   return 0;
949 }
950 
951 /*============================================================================
952 *   Conversions between frequency and radio velocity.
953 *===========================================================================*/
954 
freqvrad(double restfrq,int nfreq,int sfreq,int svrad,const double freq[],double vrad[],int stat[])955 int freqvrad(
956   double restfrq,
957   int nfreq,
958   int sfreq,
959   int svrad,
960   const double freq[],
961   double vrad[],
962   int stat[])
963 
964 {
965   double r;
966   register int ifreq, *statp;
967   register const double *freqp;
968   register double *vradp;
969 
970   if (restfrq == 0.0) {
971     return SPXERR_BAD_SPEC_PARAMS;
972   }
973   r = C/restfrq;
974 
975   freqp = freq;
976   vradp = vrad;
977   statp = stat;
978   for (ifreq = 0; ifreq < nfreq; ifreq++) {
979     *vradp = r*(restfrq - *freqp);
980     *(statp++) = 0;
981 
982     freqp += sfreq;
983     vradp += svrad;
984   }
985 
986   return 0;
987 }
988 
989 //----------------------------------------------------------------------------
990 
vradfreq(double restfrq,int nvrad,int svrad,int sfreq,const double vrad[],double freq[],int stat[])991 int vradfreq(
992   double restfrq,
993   int nvrad,
994   int svrad,
995   int sfreq,
996   const double vrad[],
997   double freq[],
998   int stat[])
999 
1000 {
1001   double r;
1002   register int ivrad, *statp;
1003   register const double *vradp;
1004   register double *freqp;
1005 
1006   r = restfrq/C;
1007 
1008   vradp = vrad;
1009   freqp = freq;
1010   statp = stat;
1011   for (ivrad = 0; ivrad < nvrad; ivrad++) {
1012     *freqp = r*(C - *vradp);
1013     *(statp++) = 0;
1014     vradp += svrad;
1015     freqp += sfreq;
1016   }
1017 
1018   return 0;
1019 }
1020 
1021 /*============================================================================
1022 *   Conversions between vacuum wavelength and optical velocity.
1023 *===========================================================================*/
1024 
wavevopt(double restwav,int nwave,int swave,int svopt,const double wave[],double vopt[],int stat[])1025 int wavevopt(
1026   double restwav,
1027   int nwave,
1028   int swave,
1029   int svopt,
1030   const double wave[],
1031   double vopt[],
1032   int stat[])
1033 
1034 {
1035   double r;
1036   register int iwave, *statp;
1037   register const double *wavep;
1038   register double *voptp;
1039 
1040   if (restwav == 0.0) {
1041     return SPXERR_BAD_SPEC_PARAMS;
1042   }
1043   r = C/restwav;
1044 
1045   wavep = wave;
1046   voptp = vopt;
1047   statp = stat;
1048   for (iwave = 0; iwave < nwave; iwave++) {
1049     *voptp = r*(*wavep) - C;
1050     *(statp++) = 0;
1051     wavep += swave;
1052     voptp += svopt;
1053   }
1054 
1055   return 0;
1056 }
1057 
1058 //----------------------------------------------------------------------------
1059 
voptwave(double restwav,int nvopt,int svopt,int swave,const double vopt[],double wave[],int stat[])1060 int voptwave(
1061   double restwav,
1062   int nvopt,
1063   int svopt,
1064   int swave,
1065   const double vopt[],
1066   double wave[],
1067   int stat[])
1068 
1069 {
1070   double r;
1071   register int ivopt, *statp;
1072   register const double *voptp;
1073   register double *wavep;
1074 
1075   r = restwav/C;
1076 
1077   voptp = vopt;
1078   wavep = wave;
1079   statp = stat;
1080   for (ivopt = 0; ivopt < nvopt; ivopt++) {
1081     *wavep = r*(C + *voptp);
1082     *(statp++) = 0;
1083     voptp += svopt;
1084     wavep += swave;
1085   }
1086 
1087   return 0;
1088 }
1089 
1090 /*============================================================================
1091 *   Conversions between vacuum wavelength and redshift.
1092 *===========================================================================*/
1093 
wavezopt(double restwav,int nwave,int swave,int szopt,const double wave[],double zopt[],int stat[])1094 int wavezopt(
1095   double restwav,
1096   int nwave,
1097   int swave,
1098   int szopt,
1099   const double wave[],
1100   double zopt[],
1101   int stat[])
1102 
1103 {
1104   double r;
1105   register int iwave, *statp;
1106   register const double *wavep;
1107   register double *zoptp;
1108 
1109   if (restwav == 0.0) {
1110     return SPXERR_BAD_SPEC_PARAMS;
1111   }
1112   r = 1.0/restwav;
1113 
1114   wavep = wave;
1115   zoptp = zopt;
1116   statp = stat;
1117   for (iwave = 0; iwave < nwave; iwave++) {
1118     *zoptp = r*(*wavep) - 1.0;
1119     *(statp++) = 0;
1120     wavep += swave;
1121     zoptp += szopt;
1122   }
1123 
1124   return 0;
1125 }
1126 
1127 //----------------------------------------------------------------------------
1128 
zoptwave(double restwav,int nzopt,int szopt,int swave,const double zopt[],double wave[],int stat[])1129 int zoptwave(
1130   double restwav,
1131   int nzopt,
1132   int szopt,
1133   int swave,
1134   const double zopt[],
1135   double wave[],
1136   int stat[])
1137 
1138 {
1139   register int izopt, *statp;
1140   register const double *zoptp;
1141   register double *wavep;
1142 
1143   zoptp = zopt;
1144   wavep = wave;
1145   statp = stat;
1146   for (izopt = 0; izopt < nzopt; izopt++) {
1147     *wavep = restwav*(1.0 + *zoptp);
1148     *(statp++) = 0;
1149     zoptp += szopt;
1150     wavep += swave;
1151   }
1152 
1153   return 0;
1154 }
1155 
1156 /*============================================================================
1157 *   Conversions between relativistic velocity and beta (= v/c).
1158 *===========================================================================*/
1159 
velobeta(double dummy,int nvelo,int svelo,int sbeta,const double velo[],double beta[],int stat[])1160 int velobeta(
1161   double dummy,
1162   int nvelo,
1163   int svelo,
1164   int sbeta,
1165   const double velo[],
1166   double beta[],
1167   int stat[])
1168 
1169 {
1170   register int ivelo, *statp;
1171   register const double *velop;
1172   register double *betap;
1173 
1174   // Avert nuisance compiler warnings about unused parameters.
1175   (void)dummy;
1176 
1177   velop = velo;
1178   betap = beta;
1179   statp = stat;
1180   for (ivelo = 0; ivelo < nvelo; ivelo++) {
1181     *betap = (*velop)/C;
1182     *(statp++) = 0;
1183 
1184     velop += svelo;
1185     betap += sbeta;
1186   }
1187 
1188   return 0;
1189 }
1190 
1191 //----------------------------------------------------------------------------
1192 
betavelo(double dummy,int nbeta,int sbeta,int svelo,const double beta[],double velo[],int stat[])1193 int betavelo(
1194   double dummy,
1195   int nbeta,
1196   int sbeta,
1197   int svelo,
1198   const double beta[],
1199   double velo[],
1200   int stat[])
1201 
1202 {
1203   register int ibeta, *statp;
1204   register const double *betap;
1205   register double *velop;
1206 
1207   // Avert nuisance compiler warnings about unused parameters.
1208   (void)dummy;
1209 
1210   betap = beta;
1211   velop = velo;
1212   statp = stat;
1213   for (ibeta = 0; ibeta < nbeta; ibeta++) {
1214     *velop = (*betap)*C;
1215     *(statp++) = 0;
1216 
1217     betap += sbeta;
1218     velop += svelo;
1219   }
1220 
1221   return 0;
1222 }
1223