head	8.7;
access;
symbols;
locks; strict;
comment	@ * @;


8.7
date	2026.05.11.12.01.10;	author mcalabre;	state Exp;
branches;
next	8.6;

8.6
date	2026.03.29.13.53.56;	author mcalabre;	state Exp;
branches
	8.6.1.1;
next	8.5;

8.5
date	2025.12.06.13.47.41;	author mcalabre;	state Exp;
branches
	8.5.1.1;
next	8.4;

8.4
date	2024.10.28.13.56.16;	author mcalabre;	state Exp;
branches
	8.4.1.1;
next	8.3;

8.3
date	2024.05.13.16.33.00;	author mcalabre;	state Exp;
branches
	8.3.1.1;
next	8.2;

8.2
date	2023.11.16.10.00.29;	author mcalabre;	state Exp;
branches
	8.2.1.1;
next	8.1;

8.1
date	2023.07.05.17.12.07;	author mcalabre;	state Exp;
branches
	8.1.1.1;
next	8.0;

8.0
date	2023.07.01.06.15.04;	author mcalabre;	state Exp;
branches
	8.0.1.1;
next	7.13;

7.13
date	2022.10.07.03.43.35;	author mcalabre;	state Exp;
branches
	7.13.1.1;
next	7.12;

7.12
date	2022.09.09.04.57.58;	author mcalabre;	state Exp;
branches
	7.12.1.1;
next	7.11;

7.11
date	2022.04.26.06.13.52;	author mcalabre;	state Exp;
branches
	7.11.1.1;
next	7.10;

7.10
date	2022.04.23.14.25.15;	author mcalabre;	state Exp;
branches
	7.10.1.1;
next	7.9;

7.9
date	2022.03.25.15.14.48;	author mcalabre;	state Exp;
branches
	7.9.1.1;
next	7.8;

7.8
date	2022.03.25.06.11.49;	author mcalabre;	state Exp;
branches
	7.8.1.1;
next	7.7;

7.7
date	2021.07.12.06.36.49;	author mcalabre;	state Exp;
branches
	7.7.1.1;
next	7.6;

7.6
date	2021.04.13.12.57.01;	author mcalabre;	state Exp;
branches
	7.6.1.1;
next	7.5;

7.5
date	2021.03.20.05.54.58;	author mcalabre;	state Exp;
branches
	7.5.1.1;
next	7.4;

7.4
date	2021.01.31.02.24.51;	author mcalabre;	state Exp;
branches
	7.4.1.1;
next	7.3;

7.3
date	2020.06.03.03.37.02;	author mcalabre;	state Exp;
branches
	7.3.1.1;
next	7.2;

7.2
date	2020.03.09.07.31.23;	author mcalabre;	state Exp;
branches
	7.2.1.1;
next	7.1;

7.1
date	2019.12.31.13.25.19;	author mcalabre;	state Exp;
branches
	7.1.1.1;
next	6.4;

6.4
date	2019.08.15.09.30.18;	author mcalabre;	state Exp;
branches
	6.4.1.1;
next	6.3;

6.3
date	2019.07.12.07.33.39;	author mcalabre;	state Exp;
branches
	6.3.1.1;
next	6.2;

6.2
date	2018.10.20.10.03.13;	author mcalabre;	state Exp;
branches
	6.2.1.1;
next	6.1;

6.1
date	2018.10.19.08.35.17;	author mcalabre;	state Exp;
branches
	6.1.1.1;
next	5.20;

5.20
date	2018.10.05.05.32.41;	author mcalabre;	state Exp;
branches
	5.20.1.1;
next	5.19;

5.19
date	2018.07.26.15.37.04;	author mcalabre;	state Exp;
branches
	5.19.1.1;
next	5.18;

5.18
date	2018.01.10.08.32.14;	author mcalabre;	state Exp;
branches
	5.18.1.1;
next	5.17;

5.17
date	2017.09.18.08.44.23;	author mcalabre;	state Exp;
branches
	5.17.1.1;
next	5.16;

5.16
date	2017.01.15.04.25.01;	author mcalabre;	state Exp;
branches
	5.16.1.1;
next	5.15;

5.15
date	2016.04.05.12.55.10;	author mcalabre;	state Exp;
branches
	5.15.1.1;
next	5.14;

5.14
date	2016.02.07.10.49.31;	author mcalabre;	state Exp;
branches
	5.14.1.1;
next	5.13;

5.13
date	2016.01.26.08.51.13;	author mcalabre;	state Exp;
branches
	5.13.1.1;
next	5.12;

5.12
date	2015.11.15.02.13.00;	author mcalabre;	state Exp;
branches
	5.12.1.1;
next	5.11;

5.11
date	2015.10.18.09.13.05;	author mcalabre;	state Exp;
branches
	5.11.1.1;
next	5.10;

5.10
date	2015.10.09.08.19.15;	author mcalabre;	state Exp;
branches
	5.10.1.1;
next	5.9;

5.9
date	2015.07.21.09.20.01;	author mcalabre;	state Exp;
branches
	5.9.1.1;
next	5.8;

5.8
date	2015.07.08.11.03.59;	author mcalabre;	state Exp;
branches
	5.8.1.1;
next	5.7;

5.7
date	2015.06.29.02.44.16;	author mcalabre;	state Exp;
branches
	5.7.1.1;
next	5.6;

5.6
date	2015.06.14.07.11.24;	author mcalabre;	state Exp;
branches
	5.6.1.1;
next	5.5;

5.5
date	2015.05.05.13.16.31;	author mcalabre;	state Exp;
branches
	5.5.1.1;
next	5.4;

5.4
date	2015.04.21.14.41.05;	author mcalabre;	state Exp;
branches
	5.4.1.1;
next	5.3;

5.3
date	2015.04.21.02.50.51;	author mcalabre;	state Exp;
branches
	5.3.1.1;
next	5.2;

5.2
date	2015.04.15.12.35.07;	author mcalabre;	state Exp;
branches
	5.2.1.1;
next	5.1;

5.1
date	2015.04.07.10.56.36;	author mcalabre;	state Exp;
branches
	5.1.1.1;
next	5.0;

5.0
date	2015.04.05.12.24.59;	author mcalabre;	state Exp;
branches
	5.0.1.1;
next	4.25;

4.25
date	2014.12.14.14.29.36;	author mcalabre;	state Exp;
branches
	4.25.1.1;
next	4.24;

4.24
date	2014.09.18.15.25.00;	author mcalabre;	state Exp;
branches
	4.24.1.1;
next	4.23;

4.23
date	2014.05.13.05.50.51;	author mcalabre;	state Exp;
branches
	4.23.1.1;
next	4.22;

4.22
date	2014.04.12.15.03.52;	author mcalabre;	state Exp;
branches
	4.22.1.1;
next	4.21;

4.21
date	2014.03.24.05.12.27;	author mcalabre;	state Exp;
branches
	4.21.1.1;
next	4.20;

4.20
date	2013.12.18.05.42.49;	author mcalabre;	state Exp;
branches
	4.20.1.1;
next	4.19;

4.19
date	2013.09.29.14.17.51;	author mcalabre;	state Exp;
branches
	4.19.1.1;
next	4.18;

4.18
date	2013.07.13.10.00.04;	author mcalabre;	state Exp;
branches
	4.18.1.1;
next	4.17;

4.17
date	2013.01.29.05.29.20;	author cal103;	state Exp;
branches
	4.17.1.1;
next	4.16;

4.16
date	2012.11.07.04.42.44;	author cal103;	state Exp;
branches
	4.16.1.1;
next	4.15;

4.15
date	2012.09.26.14.26.05;	author cal103;	state Exp;
branches
	4.15.1.1;
next	4.14;

4.14
date	2012.07.13.10.02.27;	author cal103;	state Exp;
branches
	4.14.1.1;
next	4.13;

4.13
date	2012.03.14.07.39.30;	author cal103;	state Exp;
branches
	4.13.1.1;
next	4.12;

4.12
date	2012.02.29.07.57.56;	author cal103;	state Exp;
branches
	4.12.1.1;
next	4.11;

4.11
date	2012.02.20.23.30.02;	author cal103;	state Exp;
branches
	4.11.1.1;
next	4.10;

4.10
date	2012.02.05.23.41.44;	author cal103;	state Exp;
branches
	4.10.1.1;
next	4.9;

4.9
date	2012.01.24.05.40.29;	author cal103;	state Exp;
branches
	4.9.1.1;
next	4.8;

4.8
date	2011.08.15.08.05.53;	author cal103;	state Exp;
branches
	4.8.1.1;
next	4.7;

4.7
date	2011.02.07.07.03.42;	author cal103;	state Exp;
branches
	4.7.1.1;
next	4.6;

4.6
date	2010.11.16.06.15.31;	author cal103;	state Exp;
branches
	4.6.1.1;
next	4.5;

4.5
date	2010.07.16.07.01.25;	author cal103;	state Exp;
branches
	4.5.1.1;
next	4.4;

4.4
date	2009.08.06.07.41.33;	author cal103;	state Exp;
branches
	4.4.1.1;
next	4.3;

4.3
date	2007.12.27.05.41.36;	author cal103;	state Exp;
branches
	4.3.1.1;
next	4.2;

4.2
date	2005.09.21.13.21.57;	author cal103;	state Exp;
branches
	4.2.1.1;
next	4.1;

4.1
date	2005.08.25.07.44.52;	author cal103;	state Exp;
branches;
next	4.0;

4.0
date	2005.02.04.05.07.48;	author cal103;	state Exp;
branches;
next	3.6;

3.6
date	2004.08.25.04.10.18;	author cal103;	state Exp;
branches;
next	3.5;

3.5
date	2004.06.28.02.02.37;	author mcalabre;	state Exp;
branches;
next	3.4;

3.4
date	2004.02.11.00.15.03;	author mcalabre;	state Exp;
branches;
next	3.3;

3.3
date	2003.10.22.07.20.56;	author mcalabre;	state Exp;
branches;
next	3.2;

3.2
date	2003.09.09.04.04.04;	author mcalabre;	state Exp;
branches;
next	3.1;

3.1
date	2003.04.28.03.50.41;	author mcalabre;	state Exp;
branches;
next	3.0;

3.0
date	2003.04.01.04.10.53;	author mcalabre;	state Exp;
branches;
next	2.8;

2.8
date	2002.01.30.06.04.03;	author mcalabre;	state Exp;
branches;
next	2.7;

2.7
date	2001.11.15.03.24.48;	author mcalabre;	state Exp;
branches;
next	2.6;

2.6
date	2000.03.10.01.14.42;	author mcalabre;	state Exp;
branches;
next	2.5;

2.5
date	99.06.16.00.03.19;	author mcalabre;	state Exp;
branches;
next	2.4;

2.4
date	98.02.25.07.05.50;	author mcalabre;	state Exp;
branches;
next	2.3;

2.3
date	96.05.24.07.25.36;	author mcalabre;	state Exp;
branches;
next	2.2;

2.2
date	96.05.07.20.18.03;	author mcalabre;	state Exp;
branches;
next	2.1;

2.1
date	95.09.11.07.59.38;	author mcalabre;	state Exp;
branches;
next	;

4.2.1.1
date	2005.12.05.02.39.43;	author cal103;	state Exp;
branches;
next	4.2.1.2;

4.2.1.2
date	2006.06.01.07.34.15;	author cal103;	state Exp;
branches;
next	4.2.1.3;

4.2.1.3
date	2006.06.01.07.47.53;	author cal103;	state Exp;
branches;
next	4.2.1.4;

4.2.1.4
date	2007.06.29.00.42.28;	author cal103;	state Exp;
branches;
next	4.2.1.5;

4.2.1.5
date	2007.07.11.02.01.30;	author cal103;	state Exp;
branches;
next	4.2.1.6;

4.2.1.6
date	2007.12.03.05.02.17;	author cal103;	state Exp;
branches;
next	;

4.3.1.1
date	2007.12.27.13.23.47;	author cal103;	state Exp;
branches;
next	4.3.1.2;

4.3.1.2
date	2009.07.22.04.28.39;	author cal103;	state Exp;
branches;
next	;

4.4.1.1
date	2009.08.10.08.52.49;	author cal103;	state Exp;
branches;
next	4.4.1.2;

4.4.1.2
date	2010.01.19.03.42.50;	author cal103;	state Exp;
branches;
next	;

4.5.1.1
date	2010.07.16.07.05.31;	author cal103;	state Exp;
branches;
next	;

4.6.1.1
date	2010.11.16.06.16.19;	author cal103;	state Exp;
branches;
next	4.6.1.2;

4.6.1.2
date	2011.01.14.06.33.16;	author cal103;	state Exp;
branches;
next	4.6.1.3;

4.6.1.3
date	2011.01.25.00.35.11;	author cal103;	state Exp;
branches;
next	;

4.7.1.1
date	2011.02.07.07.04.22;	author cal103;	state Exp;
branches;
next	4.7.1.2;

4.7.1.2
date	2011.07.21.03.43.08;	author cal103;	state Exp;
branches;
next	4.7.1.3;

4.7.1.3
date	2011.08.09.02.43.50;	author cal103;	state Exp;
branches;
next	4.7.1.4;

4.7.1.4
date	2011.08.10.04.17.02;	author cal103;	state Exp;
branches;
next	4.7.1.5;

4.7.1.5
date	2011.08.12.05.42.29;	author cal103;	state Exp;
branches;
next	;

4.8.1.1
date	2011.08.15.08.07.06;	author cal103;	state Exp;
branches;
next	4.8.1.2;

4.8.1.2
date	2011.11.17.03.07.49;	author cal103;	state Exp;
branches;
next	4.8.1.3;

4.8.1.3
date	2012.01.24.05.23.06;	author cal103;	state Exp;
branches;
next	;

4.9.1.1
date	2012.01.24.05.41.45;	author cal103;	state Exp;
branches;
next	;

4.10.1.1
date	2012.02.05.23.42.46;	author cal103;	state Exp;
branches;
next	;

4.11.1.1
date	2012.02.20.23.31.13;	author cal103;	state Exp;
branches;
next	;

4.12.1.1
date	2012.02.29.07.59.10;	author cal103;	state Exp;
branches;
next	4.12.1.2;

4.12.1.2
date	2012.03.14.06.41.42;	author cal103;	state Exp;
branches;
next	;

4.13.1.1
date	2012.03.14.07.40.37;	author cal103;	state Exp;
branches;
next	4.13.1.2;

4.13.1.2
date	2012.07.13.03.34.20;	author cal103;	state Exp;
branches;
next	;

4.14.1.1
date	2012.07.13.10.04.44;	author cal103;	state Exp;
branches;
next	;

4.15.1.1
date	2012.09.26.14.27.51;	author cal103;	state Exp;
branches;
next	;

4.16.1.1
date	2012.11.07.04.45.56;	author cal103;	state Exp;
branches;
next	4.16.1.2;

4.16.1.2
date	2013.01.29.05.09.44;	author cal103;	state Exp;
branches;
next	;

4.17.1.1
date	2013.01.29.05.32.32;	author cal103;	state Exp;
branches;
next	;

4.18.1.1
date	2013.07.13.10.02.37;	author mcalabre;	state Exp;
branches;
next	;

4.19.1.1
date	2013.09.29.14.20.38;	author mcalabre;	state Exp;
branches;
next	;

4.20.1.1
date	2013.12.18.05.46.55;	author mcalabre;	state Exp;
branches;
next	4.20.1.2;

4.20.1.2
date	2014.03.21.06.32.19;	author mcalabre;	state Exp;
branches;
next	;

4.21.1.1
date	2014.03.24.05.15.28;	author mcalabre;	state Exp;
branches;
next	;

4.22.1.1
date	2014.04.12.15.06.32;	author mcalabre;	state Exp;
branches;
next	;

4.23.1.1
date	2014.05.13.05.53.49;	author mcalabre;	state Exp;
branches;
next	;

4.24.1.1
date	2014.09.18.15.28.09;	author mcalabre;	state Exp;
branches;
next	;

4.25.1.1
date	2014.12.14.14.32.45;	author mcalabre;	state Exp;
branches;
next	4.25.1.2;

4.25.1.2
date	2015.01.06.01.01.06;	author mcalabre;	state Exp;
branches;
next	4.25.1.3;

4.25.1.3
date	2015.04.03.02.22.45;	author mcalabre;	state Exp;
branches;
next	4.25.1.4;

4.25.1.4
date	2015.04.03.04.09.46;	author mcalabre;	state Exp;
branches;
next	;

5.0.1.1
date	2015.04.05.12.28.00;	author mcalabre;	state Exp;
branches;
next	5.0.1.2;

5.0.1.2
date	2015.04.07.08.46.25;	author mcalabre;	state Exp;
branches;
next	;

5.1.1.1
date	2015.04.07.11.01.10;	author mcalabre;	state Exp;
branches;
next	5.1.1.2;

5.1.1.2
date	2015.04.07.23.28.05;	author mcalabre;	state Exp;
branches;
next	5.1.1.3;

5.1.1.3
date	2015.04.07.23.43.33;	author mcalabre;	state Exp;
branches;
next	5.1.1.4;

5.1.1.4
date	2015.04.13.08.24.25;	author mcalabre;	state Exp;
branches;
next	5.1.1.5;

5.1.1.5
date	2015.04.15.09.16.34;	author mcalabre;	state Exp;
branches;
next	;

5.2.1.1
date	2015.04.15.12.39.14;	author mcalabre;	state Exp;
branches;
next	5.2.1.2;

5.2.1.2
date	2015.04.21.01.38.48;	author mcalabre;	state Exp;
branches;
next	;

5.3.1.1
date	2015.04.21.02.54.02;	author mcalabre;	state Exp;
branches;
next	;

5.4.1.1
date	2015.04.21.14.44.28;	author mcalabre;	state Exp;
branches;
next	;

5.5.1.1
date	2015.05.05.13.21.00;	author mcalabre;	state Exp;
branches;
next	;

5.6.1.1
date	2015.06.14.07.14.44;	author mcalabre;	state Exp;
branches;
next	;

5.7.1.1
date	2015.06.29.02.47.24;	author mcalabre;	state Exp;
branches;
next	;

5.8.1.1
date	2015.07.08.11.07.18;	author mcalabre;	state Exp;
branches;
next	;

5.9.1.1
date	2015.07.21.09.28.07;	author mcalabre;	state Exp;
branches;
next	;

5.10.1.1
date	2015.10.09.08.22.35;	author mcalabre;	state Exp;
branches;
next	;

5.11.1.1
date	2015.10.18.09.16.27;	author mcalabre;	state Exp;
branches;
next	;

5.12.1.1
date	2015.11.15.02.16.14;	author mcalabre;	state Exp;
branches;
next	5.12.1.2;

5.12.1.2
date	2016.01.25.05.17.04;	author mcalabre;	state Exp;
branches;
next	;

5.13.1.1
date	2016.01.26.08.54.32;	author mcalabre;	state Exp;
branches;
next	;

5.14.1.1
date	2016.02.07.10.52.44;	author mcalabre;	state Exp;
branches;
next	;

5.15.1.1
date	2016.04.05.12.58.35;	author mcalabre;	state Exp;
branches;
next	5.15.1.2;

5.15.1.2
date	2017.01.15.04.13.33;	author mcalabre;	state Exp;
branches;
next	;

5.16.1.1
date	2017.01.15.04.28.59;	author mcalabre;	state Exp;
branches;
next	;

5.17.1.1
date	2017.09.18.08.45.59;	author mcalabre;	state Exp;
branches;
next	5.17.1.2;

5.17.1.2
date	2017.12.05.01.41.54;	author mcalabre;	state Exp;
branches;
next	5.17.1.3;

5.17.1.3
date	2017.12.05.07.39.40;	author mcalabre;	state Exp;
branches;
next	5.17.1.4;

5.17.1.4
date	2017.12.05.21.13.56;	author mcalabre;	state Exp;
branches;
next	5.17.1.5;

5.17.1.5
date	2018.01.10.08.25.34;	author mcalabre;	state Exp;
branches;
next	;

5.18.1.1
date	2018.01.10.08.33.04;	author mcalabre;	state Exp;
branches;
next	5.18.1.2;

5.18.1.2
date	2018.07.25.06.21.08;	author mcalabre;	state Exp;
branches;
next	;

5.19.1.1
date	2018.07.26.15.41.40;	author mcalabre;	state Exp;
branches;
next	;

5.20.1.1
date	2018.10.05.05.33.33;	author mcalabre;	state Exp;
branches;
next	;

6.1.1.1
date	2018.10.19.08.36.15;	author mcalabre;	state Exp;
branches;
next	;

6.2.1.1
date	2018.10.20.10.04.15;	author mcalabre;	state Exp;
branches;
next	6.2.1.2;

6.2.1.2
date	2019.05.10.01.56.50;	author mcalabre;	state Exp;
branches;
next	6.2.1.3;

6.2.1.3
date	2019.07.08.13.07.51;	author mcalabre;	state Exp;
branches;
next	6.2.1.4;

6.2.1.4
date	2019.07.09.08.47.43;	author mcalabre;	state Exp;
branches;
next	;

6.3.1.1
date	2019.07.12.07.34.37;	author mcalabre;	state Exp;
branches;
next	;

6.4.1.1
date	2019.08.15.09.31.29;	author mcalabre;	state Exp;
branches;
next	6.4.1.2;

6.4.1.2
date	2019.12.31.03.28.03;	author mcalabre;	state Exp;
branches;
next	;

7.1.1.1
date	2019.12.31.13.28.19;	author mcalabre;	state Exp;
branches;
next	;

7.2.1.1
date	2020.03.09.07.34.50;	author mcalabre;	state Exp;
branches;
next	;

7.3.1.1
date	2020.06.03.03.38.10;	author mcalabre;	state Exp;
branches;
next	7.3.1.2;

7.3.1.2
date	2020.08.17.11.19.09;	author mcalabre;	state Exp;
branches;
next	7.3.1.3;

7.3.1.3
date	2020.09.21.08.24.44;	author mcalabre;	state Exp;
branches;
next	7.3.1.4;

7.3.1.4
date	2021.01.19.14.09.10;	author mcalabre;	state Exp;
branches;
next	7.3.1.5;

7.3.1.5
date	2021.01.28.12.29.30;	author mcalabre;	state Exp;
branches;
next	;

7.4.1.1
date	2021.01.31.02.26.24;	author mcalabre;	state Exp;
branches;
next	;

7.5.1.1
date	2021.03.20.05.56.42;	author mcalabre;	state Exp;
branches;
next	7.5.1.2;

7.5.1.2
date	2021.04.13.09.20.16;	author mcalabre;	state Exp;
branches;
next	;

7.6.1.1
date	2021.04.13.13.00.35;	author mcalabre;	state Exp;
branches;
next	7.6.1.2;

7.6.1.2
date	2021.07.01.07.39.45;	author mcalabre;	state Exp;
branches;
next	7.6.1.3;

7.6.1.3
date	2021.07.01.07.50.34;	author mcalabre;	state Exp;
branches;
next	7.6.1.4;

7.6.1.4
date	2021.07.02.08.07.37;	author mcalabre;	state Exp;
branches;
next	;

7.7.1.1
date	2021.07.12.06.38.27;	author mcalabre;	state Exp;
branches;
next	7.7.1.2;

7.7.1.2
date	2022.03.25.06.05.59;	author mcalabre;	state Exp;
branches;
next	;

7.8.1.1
date	2022.03.25.06.14.14;	author mcalabre;	state Exp;
branches;
next	;

7.9.1.1
date	2022.03.25.15.16.40;	author mcalabre;	state Exp;
branches;
next	;

7.10.1.1
date	2022.04.23.14.26.54;	author mcalabre;	state Exp;
branches;
next	;

7.11.1.1
date	2022.04.26.06.15.32;	author mcalabre;	state Exp;
branches;
next	;

7.12.1.1
date	2022.09.09.05.00.36;	author mcalabre;	state Exp;
branches;
next	;

7.13.1.1
date	2022.10.07.03.45.47;	author mcalabre;	state Exp;
branches;
next	7.13.1.2;

7.13.1.2
date	2023.06.15.04.17.19;	author mcalabre;	state Exp;
branches;
next	;

8.0.1.1
date	2023.07.01.06.22.44;	author mcalabre;	state Exp;
branches;
next	;

8.1.1.1
date	2023.07.05.17.15.00;	author mcalabre;	state Exp;
branches;
next	;

8.2.1.1
date	2023.11.16.10.05.57;	author mcalabre;	state Exp;
branches;
next	8.2.1.2;

8.2.1.2
date	2023.11.29.07.36.19;	author mcalabre;	state Exp;
branches;
next	8.2.1.3;

8.2.1.3
date	2024.04.02.14.01.58;	author mcalabre;	state Exp;
branches;
next	8.2.1.4;

8.2.1.4
date	2024.05.08.08.52.30;	author mcalabre;	state Exp;
branches;
next	8.2.1.5;

8.2.1.5
date	2024.05.08.15.14.26;	author mcalabre;	state Exp;
branches;
next	8.2.1.6;

8.2.1.6
date	2024.05.08.15.39.34;	author mcalabre;	state Exp;
branches;
next	8.2.1.7;

8.2.1.7
date	2024.05.10.14.32.14;	author mcalabre;	state Exp;
branches;
next	8.2.1.8;

8.2.1.8
date	2024.05.13.05.05.56;	author mcalabre;	state Exp;
branches;
next	;

8.3.1.1
date	2024.05.13.16.35.39;	author mcalabre;	state Exp;
branches;
next	8.3.1.2;

8.3.1.2
date	2024.07.09.08.49.16;	author mcalabre;	state Exp;
branches;
next	;

8.4.1.1
date	2024.10.28.13.58.41;	author mcalabre;	state Exp;
branches;
next	8.4.1.2;

8.4.1.2
date	2025.10.12.12.50.05;	author mcalabre;	state Exp;
branches;
next	8.4.1.3;

8.4.1.3
date	2025.12.06.13.37.15;	author mcalabre;	state Exp;
branches;
next	;

8.5.1.1
date	2025.12.06.14.05.15;	author mcalabre;	state Exp;
branches;
next	8.5.1.2;

8.5.1.2
date	2026.03.26.12.24.05;	author mcalabre;	state Exp;
branches;
next	8.5.1.3;

8.5.1.3
date	2026.03.29.13.36.16;	author mcalabre;	state Exp;
branches;
next	;

8.6.1.1
date	2026.03.29.14.19.26;	author mcalabre;	state Exp;
branches;
next	8.6.1.2;

8.6.1.2
date	2026.04.05.08.25.58;	author mcalabre;	state Exp;
branches;
next	8.6.1.3;

8.6.1.3
date	2026.04.13.06.15.02;	author mcalabre;	state Exp;
branches;
next	;


desc
@Implementation of the WCS linear transformation equations.
@


8.7
log
@WCSLIB 8.7
@
text
@/*============================================================================
  WCSLIB 8.7 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2026, Mark Calabretta

  This file is part of WCSLIB.

  WCSLIB is free software: you can redistribute it and/or modify it under the
  terms of the GNU Lesser General Public License as published by the Free
  Software Foundation, either version 3 of the License, or (at your option)
  any later version.

  WCSLIB is distributed in the hope that it will be useful, but WITHOUT ANY
  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
  more details.

  You should have received a copy of the GNU Lesser General Public License
  along with WCSLIB.  If not, see http://www.gnu.org/licenses.

  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
  http://www.atnf.csiro.au/computing/software/wcs
  $Id: lin.c,v 8.6.1.3 2026/04/13 06:15:02 mcalabre Exp mcalabre $
*===========================================================================*/

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "wcserr.h"
#include "wcslimits.h"
#include "wcsprintf.h"
#include "lin.h"
#include "dis.h"

// Map status return value to message.
const char *lin_errmsg[] = {
  "Success",
  "Null linprm pointer passed",
  "Memory allocation failed",
  "Invalid parameter value",
  "PCi_ja matrix is singular",
  "Failed to initialize distortion functions",
  "Distort error",
  "De-distort error"};

// Map error returns for lower-level routines.
const int lin_diserr[] = {
  LINERR_SUCCESS,		//  0: DISERR_SUCCESS
  LINERR_NULL_POINTER,		//  1: DISERR_NULL_POINTER
  LINERR_MEMORY,		//  2: DISERR_MEMORY
  LINERR_DISTORT_INIT,		//  3: DISERR_BAD_PARAM
  LINERR_DISTORT,		//  4: DISERR_DISTORT
  LINERR_DEDISTORT		//  5: DISERR_DEDISTORT
};

static const int LINSET = 137;

// Convenience macro for invoking wcserr_set().
#define LIN_ERRMSG(status) WCSERR_SET(status), lin_errmsg[status]

//----------------------------------------------------------------------------

int linini(int alloc, int naxis, struct linprm *lin)

{
  return lininit(alloc, naxis, lin, -1);
}

//----------------------------------------------------------------------------

int lininit(int alloc, int naxis, struct linprm *lin, int ndpmax)

{
  static const char *function = "lininit";

  if (lin == 0x0) return LINERR_NULL_POINTER;

  // Initialize error message handling.
  if (lin->flag == -1) {
    lin->err = 0x0;
  }
  struct wcserr **err = &(lin->err);
  wcserr_clear(err);


  // Initialize memory management.
  if (lin->flag == -1 || lin->m_flag != LINSET) {
    if (lin->flag == -1) {
      lin->dispre = 0x0;
      lin->disseq = 0x0;
      lin->dummy  = 0x0;
    }

    lin->m_flag   = 0;
    lin->m_naxis  = 0;
    lin->m_crpix  = 0x0;
    lin->m_pc     = 0x0;
    lin->m_cdelt  = 0x0;
    lin->m_dispre = 0x0;
    lin->m_disseq = 0x0;
  }

  // Sanity check on naxis.
  if (naxis < 0) {
    return wcserr_set(WCSERR_SET(LINERR_BAD_PARAM),
      "naxis must not be negative (got %d)", naxis);
  }

  if (NAXMAX < naxis) {
    return wcserr_set(WCSERR_SET(LINERR_BAD_PARAM),
      "naxis exceeds %d (got %d)", NAXMAX, naxis);
  }


  // Allocate memory for arrays if required.
  if (alloc ||
      lin->crpix  == 0x0 ||
      lin->pc     == 0x0 ||
      lin->cdelt  == 0x0) {

    // Was sufficient allocated previously?
    if (lin->m_flag == LINSET && lin->m_naxis < naxis) {
      // No, free it.
      linfree(lin);
    }

    if (alloc || lin->crpix == 0x0) {
      if (lin->m_crpix) {
        // In case the caller fiddled with it.
        lin->crpix = lin->m_crpix;

      } else {
        if ((lin->crpix = calloc(naxis, sizeof(double))) == 0x0) {
          return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
        }

        lin->m_flag  = LINSET;
        lin->m_naxis = naxis;
        lin->m_crpix = lin->crpix;
      }
    }

    if (alloc || lin->pc == 0x0) {
      if (lin->m_pc) {
        // In case the caller fiddled with it.
        lin->pc = lin->m_pc;

      } else {
        size_t naxszt = naxis;
        if ((lin->pc = calloc(naxszt*naxszt, sizeof(double))) == 0x0) {
          linfree(lin);
          return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
        }

        lin->m_flag  = LINSET;
        lin->m_naxis = naxis;
        lin->m_pc    = lin->pc;
      }
    }

    if (alloc || lin->cdelt == 0x0) {
      if (lin->m_cdelt) {
        // In case the caller fiddled with it.
        lin->cdelt = lin->m_cdelt;

      } else {
        if ((lin->cdelt = calloc(naxis, sizeof(double))) == 0x0) {
          linfree(lin);
          return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
        }

        lin->m_flag  = LINSET;
        lin->m_naxis = naxis;
        lin->m_cdelt = lin->cdelt;
      }
    }
  }


  // Reinitialize disprm structs if we are managing them.
  if (lin->m_dispre) {
    disinit(1, naxis, lin->dispre, ndpmax);
  }

  if (lin->m_disseq) {
    disinit(1, naxis, lin->disseq, ndpmax);
  }


  // Free memory allocated by linset().
  if (abs(lin->flag) == LINSET) {
    if (lin->piximg) free(lin->piximg);
    if (lin->imgpix) free(lin->imgpix);
  }

  lin->piximg  = 0x0;
  lin->imgpix  = 0x0;
  lin->i_naxis = 0;
  lin->unity   = 0;
  lin->affine  = 0;
  lin->simple  = 0;


  lin->naxis = naxis;

  // CRPIXja defaults to 0.0.
  for (int j = 0; j < naxis; j++) {
    lin->crpix[j] = 0.0;
  }

  // PCi_ja defaults to the unit matrix.
  double *pc = lin->pc;
  for (int i = 0; i < naxis; i++) {
    for (int j = 0; j < naxis; j++) {
      if (j == i) {
        *pc = 1.0;
      } else {
        *pc = 0.0;
      }
      pc++;
    }
  }

  // CDELTia defaults to 1.0.
  for (int i = 0; i < naxis; i++) {
    lin->cdelt[i] = 1.0;
  }

  lin->flag = 0;

  return 0;
}

//----------------------------------------------------------------------------

int lindis(int sequence, struct linprm *lin, struct disprm *dis)

{
  return lindist(sequence, lin, dis, -1);
}

//----------------------------------------------------------------------------

int lindist(int sequence, struct linprm *lin, struct disprm *dis, int ndpmax)

{
  static const char *function = "lindist";

  if (lin == 0x0) return LINERR_NULL_POINTER;
  struct wcserr **err = &(lin->err);

  if (sequence == 1) {
    if (lin->m_dispre) {
      disfree(lin->m_dispre);
      free(lin->m_dispre);
    }

    lin->dispre   = dis;
    lin->m_flag   = LINSET;
    lin->m_dispre = dis;

  } else if (sequence == 2) {
    if (lin->m_disseq) {
      disfree(lin->m_disseq);
      free(lin->m_disseq);
    }

    lin->disseq   = dis;
    lin->m_flag   = LINSET;
    lin->m_disseq = dis;

  } else {
    return wcserr_set(WCSERR_SET(LINERR_DISTORT_INIT),
      "Invalid sequence (%d)", sequence);
  }

  if (dis) {
    int status = disinit(1, lin->naxis, dis, ndpmax);
    if (status) {
      return wcserr_set(LIN_ERRMSG(lin_diserr[status]));
    }
  }

  return 0;
}

//----------------------------------------------------------------------------

int lincpy(int alloc, const struct linprm *linsrc, struct linprm *lindst)

{
  static const char *function = "lincpy";

  if (linsrc == 0x0) return LINERR_NULL_POINTER;
  if (lindst == 0x0) return LINERR_NULL_POINTER;
  struct wcserr **err = &(lindst->err);

  int naxis = linsrc->naxis;
  if (naxis < 1) {
    return wcserr_set(WCSERR_SET(LINERR_MEMORY),
      "naxis must be positive (got %d)", naxis);
  }

  int status = lininit(alloc, naxis, lindst, 0);
  if (status) {
    return status;
  }

  const double *srcp = linsrc->crpix;
  double *dstp = lindst->crpix;
  for (int j = 0; j < naxis; j++) {
    *(dstp++) = *(srcp++);
  }

  srcp = linsrc->pc;
  dstp = lindst->pc;
  for (int i = 0; i < naxis; i++) {
    for (int j = 0; j < naxis; j++) {
      *(dstp++) = *(srcp++);
    }
  }

  srcp = linsrc->cdelt;
  dstp = lindst->cdelt;
  for (int i = 0; i < naxis; i++) {
    *(dstp++) = *(srcp++);
  }

  if (linsrc->dispre) {
    if (!lindst->dispre) {
      if ((lindst->dispre = calloc(1, sizeof(struct disprm))) == 0x0) {
        return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
      }

      lindst->m_dispre = lindst->dispre;
    }

    if ((status = discpy(alloc, linsrc->dispre, lindst->dispre))) {
      status = wcserr_set(LIN_ERRMSG(lin_diserr[status]));
      goto cleanup;
    }
  }

  if (linsrc->disseq) {
    if (!lindst->disseq) {
      if ((lindst->disseq = calloc(1, sizeof(struct disprm))) == 0x0) {
        return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
      }

      lindst->m_disseq = lindst->disseq;
    }

    if ((status = discpy(alloc, linsrc->disseq, lindst->disseq))) {
      status = wcserr_set(LIN_ERRMSG(lin_diserr[status]));
      goto cleanup;
    }
  }

cleanup:
  if (status) {
    if (lindst->m_dispre) {
      disfree(lindst->m_dispre);
      free(lindst->m_dispre);
      lindst->m_dispre = 0x0;
      lindst->dispre = 0x0;
    }

    if (lindst->m_disseq) {
      disfree(lindst->m_disseq);
      free(lindst->m_disseq);
      lindst->m_disseq = 0x0;
      lindst->disseq = 0x0;
    }
  }

  return status;
}

//----------------------------------------------------------------------------

int linfree(struct linprm *lin)

{
  if (lin == 0x0) return LINERR_NULL_POINTER;

  if (lin->flag != -1) {
    // Optionally allocated by lininit() for given parameters.
    if (lin->m_flag == LINSET) {
      if (lin->crpix  == lin->m_crpix)  lin->crpix  = 0x0;
      if (lin->pc     == lin->m_pc)     lin->pc     = 0x0;
      if (lin->cdelt  == lin->m_cdelt)  lin->cdelt  = 0x0;
      if (lin->dispre == lin->m_dispre) lin->dispre = 0x0;
      if (lin->disseq == lin->m_disseq) lin->disseq = 0x0;

      if (lin->m_crpix)  free(lin->m_crpix);
      if (lin->m_pc)     free(lin->m_pc);
      if (lin->m_cdelt)  free(lin->m_cdelt);

      if (lin->m_dispre) {
        disfree(lin->m_dispre);
        free(lin->m_dispre);
      }

      if (lin->m_disseq) {
        disfree(lin->m_disseq);
        free(lin->m_disseq);
      }
    }

    // Allocated unconditionally by linset().
    if (lin->piximg) free(lin->piximg);
    if (lin->imgpix) free(lin->imgpix);
  }


  lin->m_flag   = 0;
  lin->m_naxis  = 0;
  lin->m_crpix  = 0x0;
  lin->m_pc     = 0x0;
  lin->m_cdelt  = 0x0;
  lin->m_dispre = 0x0;
  lin->m_disseq = 0x0;

  lin->piximg   = 0x0;
  lin->imgpix   = 0x0;
  lin->i_naxis  = 0;

  wcserr_clear(&(lin->err));

  lin->flag = 0;

  return 0;
}

//----------------------------------------------------------------------------

int linsize(const struct linprm *lin, int sizes[2])

{
  if (lin == 0x0) {
    sizes[0] = sizes[1] = 0;
    return 0;
  }

  // Base size, in bytes.
  sizes[0] = sizeof(struct linprm);

  // Total size of allocated memory, in bytes.
  sizes[1] = 0;

  int naxis = lin->naxis;
  int naxsiz = naxis * (int)(sizeof(double));

  // linprm::crpix[].
  sizes[1] += naxsiz;

  // linprm::pc[].
  sizes[1] += naxis*naxsiz;

  // linprm::cdelt[].
  sizes[1] += naxsiz;

  // linprm::dispre[].
  int exsizes[2];
  dissize(lin->dispre, exsizes);
  sizes[1] += exsizes[0] + exsizes[1];

  // linprm::disseq[].
  dissize(lin->disseq, exsizes);
  sizes[1] += exsizes[0] + exsizes[1];

  // linprm::err[].
  wcserr_size(lin->err, exsizes);
  sizes[1] += exsizes[0] + exsizes[1];

  // The remaining arrays are allocated unconditionally by linset().
  if (abs(lin->flag) != LINSET) {
    return 0;
  }

  // linprm::piximg[].
  sizes[1] += naxis*naxsiz;

  // linprm::imgpix[].
  sizes[1] += naxis*naxsiz;

  return 0;
}

//----------------------------------------------------------------------------

int linenq(const struct linprm *lin, int enquiry)

{
  // Initialize.
  if (lin == 0x0) return LINERR_NULL_POINTER;

  int answer = 0;

  if (enquiry & LINENQ_MEM) {
    if (lin->m_flag != LINSET) return 0;
    answer = 1;
  }

  if (enquiry & LINENQ_SET) {
    if (abs(lin->flag) != LINSET) return 0;
    answer = 1;
  }

  if (enquiry & LINENQ_BYP) {
    if (lin->flag != 1 && lin->flag != -LINSET) return 0;
    answer = 1;
  }

  return answer;
}

//----------------------------------------------------------------------------

int linprt(const struct linprm *lin)

{
  if (lin == 0x0) return LINERR_NULL_POINTER;

  if (abs(lin->flag) != LINSET) {
    wcsprintf("The linprm struct is UNINITIALIZED.\n");
    return 0;
  }

  // Parameters supplied.
  wcsprintf("       flag: %d\n", lin->flag);
  wcsprintf("      naxis: %d\n", lin->naxis);

  WCSPRINTF_PTR("      crpix: ", lin->crpix, "\n");
  wcsprintf("            ");
  for (int j = 0; j < lin->naxis; j++) {
    wcsprintf("  %#- 11.5g", lin->crpix[j]);
  }
  wcsprintf("\n");

  int k = 0;
  WCSPRINTF_PTR("         pc: ", lin->pc, "\n");
  for (int i = 0; i < lin->naxis; i++) {
    wcsprintf("    pc[%d][]:", i);
    for (int j = 0; j < lin->naxis; j++) {
      wcsprintf("  %#- 11.5g", lin->pc[k++]);
    }
    wcsprintf("\n");
  }

  WCSPRINTF_PTR("      cdelt: ", lin->cdelt, "\n");
  wcsprintf("            ");
  for (int i = 0; i < lin->naxis; i++) {
    wcsprintf("  %#- 11.5g", lin->cdelt[i]);
  }
  wcsprintf("\n");

  WCSPRINTF_PTR("     dispre: ", lin->dispre, "");
  if (lin->dispre != 0x0) wcsprintf("  (see below)");
  wcsprintf("\n");
  WCSPRINTF_PTR("     disseq: ", lin->disseq, "");
  if (lin->disseq != 0x0) wcsprintf("  (see below)");
  wcsprintf("\n");

  // Derived values.
  if (lin->piximg == 0x0) {
    wcsprintf("     piximg: (nil)\n");
  } else {
    int k = 0;
    for (int i = 0; i < lin->naxis; i++) {
      wcsprintf("piximg[%d][]:", i);
      for (int j = 0; j < lin->naxis; j++) {
        wcsprintf("  %#- 11.5g", lin->piximg[k++]);
      }
      wcsprintf("\n");
    }
  }

  if (lin->imgpix == 0x0) {
    wcsprintf("     imgpix: (nil)\n");
  } else {
    int k = 0;
    for (int i = 0; i < lin->naxis; i++) {
      wcsprintf("imgpix[%d][]:", i);
      for (int j = 0; j < lin->naxis; j++) {
        wcsprintf("  %#- 11.5g", lin->imgpix[k++]);
      }
      wcsprintf("\n");
    }
  }

  wcsprintf("    i_naxis: %d\n", lin->i_naxis);
  wcsprintf("      unity: %d\n", lin->unity);
  wcsprintf("     affine: %d\n", lin->affine);
  wcsprintf("     simple: %d\n", lin->simple);

  // Error handling.
  WCSPRINTF_PTR("        err: ", lin->err, "\n");
  if (lin->err) {
    wcserr_prt(lin->err, "             ");
  }

  // Memory management.
  wcsprintf("     m_flag: %d\n", lin->m_flag);
  wcsprintf("    m_naxis: %d\n", lin->m_naxis);
  WCSPRINTF_PTR("    m_crpix: ", lin->m_crpix, "");
  if (lin->m_crpix == lin->crpix) wcsprintf("  (= crpix)");
  wcsprintf("\n");
  WCSPRINTF_PTR("       m_pc: ", lin->m_pc, "");
  if (lin->m_pc == lin->pc) wcsprintf("  (= pc)");
  wcsprintf("\n");
  WCSPRINTF_PTR("    m_cdelt: ", lin->m_cdelt, "");
  if (lin->m_cdelt == lin->cdelt) wcsprintf("  (= cdelt)");
  wcsprintf("\n");
  WCSPRINTF_PTR("   m_dispre: ", lin->m_dispre, "");
  if (lin->dispre && lin->m_dispre == lin->dispre) wcsprintf("  (= dispre)");
  wcsprintf("\n");
  WCSPRINTF_PTR("   m_disseq: ", lin->m_disseq, "");
  if (lin->disseq && lin->m_disseq == lin->disseq) wcsprintf("  (= disseq)");
  wcsprintf("\n");

  // Distortion parameters (from above).
  if (lin->dispre) {
    wcsprintf("\n");
    wcsprintf("dispre.*\n");
    disprt(lin->dispre);
  }

  if (lin->disseq) {
    wcsprintf("\n");
    wcsprintf("disseq.*\n");
    disprt(lin->disseq);
  }

  return 0;
}

//----------------------------------------------------------------------------

int linperr(const struct linprm *lin, const char *prefix)

{
  if (lin == 0x0) return LINERR_NULL_POINTER;

  if (lin->err && wcserr_prt(lin->err, prefix) == 0) {
    if (lin->dispre) wcserr_prt(lin->dispre->err, prefix);
    if (lin->disseq) wcserr_prt(lin->disseq->err, prefix);
  }

  return 0;
}

//----------------------------------------------------------------------------

int linset(struct linprm *lin)

{
  static const char *function = "linset";

  if (lin == 0x0) return LINERR_NULL_POINTER;
  if (lin->flag == -LINSET) return 0;
  struct wcserr **err = &(lin->err);

  int naxis = lin->naxis;

  // Check for a unit matrix.
  lin->unity = 1;
  double *pc = lin->pc;
  for (int i = 0; i < naxis; i++) {
    for (int j = 0; j < naxis; j++) {
      if (j == i) {
        if (*(pc++) != 1.0) {
          lin->unity = 0;
          break;
        }
      } else {
        if (*(pc++) != 0.0) {
          lin->unity = 0;
          break;
        }
      }
    }
  }


  if (lin->unity) {
    if (abs(lin->flag) == LINSET) {
      // Free memory that may have been allocated previously.
      if (lin->piximg) free(lin->piximg);
      if (lin->imgpix) free(lin->imgpix);
    }

    lin->piximg  = 0x0;
    lin->imgpix  = 0x0;
    lin->i_naxis = 0;

    // Check cdelt.
    for (int i = 0; i < naxis; i++) {
      if (lin->cdelt[i] == 0.0) {
        return wcserr_set(LIN_ERRMSG(LINERR_SINGULAR_MTX));
      }
    }

  } else {
    if (abs(lin->flag) != LINSET || lin->i_naxis < naxis) {
      if (abs(lin->flag) == LINSET) {
        // Free memory that may have been allocated previously.
        if (lin->piximg) free(lin->piximg);
        if (lin->imgpix) free(lin->imgpix);
      }

      // Allocate memory for internal arrays.
      size_t naxszt = naxis;
      if ((lin->piximg = calloc(naxszt*naxszt, sizeof(double))) == 0x0) {
        return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
      }

      if ((lin->imgpix = calloc(naxszt*naxszt, sizeof(double))) == 0x0) {
        free(lin->piximg);
        return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
      }

      lin->i_naxis = naxis;
    }

    // Compute the pixel-to-image transformation matrix.
    pc = lin->pc;
    double *piximg = lin->piximg;
    for (int i = 0; i < naxis; i++) {
      if (lin->disseq == 0x0) {
        // No sequent distortions.  Incorporate cdelt into piximg.
        for (int j = 0; j < naxis; j++) {
          *(piximg++) = lin->cdelt[i] * (*(pc++));
        }
      } else {
        for (int j = 0; j < naxis; j++) {
          *(piximg++) = *(pc++);
        }
      }
    }

    // Compute the image-to-pixel transformation matrix.
    int status = matinv(naxis, lin->piximg, lin->imgpix);
    if (status) {
      return wcserr_set(LIN_ERRMSG(status));
    }
  }


  // Set up the distortion functions.
  lin->affine = 1;
  if (lin->dispre) {
    (lin->dispre)->flag = 0;
    int status = disset(lin->dispre);
    if (status) {
      return wcserr_set(LIN_ERRMSG(lin_diserr[status]));
    }

    lin->affine = 0;
  }

  if (lin->disseq) {
    (lin->disseq)->flag = 0;
    int status = disset(lin->disseq);
    if (status) {
      return wcserr_set(LIN_ERRMSG(lin_diserr[status]));
    }

    lin->affine = 0;
  }

  lin->simple = lin->unity && lin->affine;

  lin->flag = (lin->flag == 1) ? -LINSET : LINSET;

  return 0;
}

//----------------------------------------------------------------------------

int linp2x(
  struct linprm *lin,
  int ncoord,
  int nelem,
  const double pixcrd[],
  double imgcrd[])

{
  static const char *function = "linp2x";

  // Initialize.
  if (lin == 0x0) return LINERR_NULL_POINTER;
  struct wcserr **err = &(lin->err);

  if (abs(lin->flag) != LINSET) {
    int status = linset(lin);
    if (status) {
      return status;
    }
  }

  int naxis = lin->naxis;


  // Convert pixel coordinates to intermediate world coordinates.
  const double *pix = pixcrd;
  double *img = imgcrd;

  if (lin->simple) {
    // Handle the simplest and most common case with maximum efficiency.
    int nelemn = nelem - naxis;
    for (int k = 0; k < ncoord; k++) {
      for (int i = 0; i < naxis; i++) {
        *(img++) = lin->cdelt[i] * (*(pix++) - lin->crpix[i]);
      }

      pix += nelemn;
      img += nelemn;
    }

  } else if (lin->affine) {
    // No distortions.
    size_t naxsiz = naxis * sizeof(double);
    int nelemn = nelem - naxis;
    for (int k = 0; k < ncoord; k++) {
      memset(img, 0, naxsiz);

      for (int j = 0; j < naxis; j++) {
        // cdelt will have been incorporated into piximg.
        double *piximg = lin->piximg + j;

        // Column-wise multiplication allows this to be cached.
        double temp = *(pix++) - lin->crpix[j];
        for (int i = 0; i < naxis; i++, piximg += naxis) {
          if (*piximg != 0.0) {
            // Skipped if *piximg == 0.0 in case temp is NaN, noting that
            // zero * NaN = NaN.  Thus, if the PCij matrix is diagonal, this
            // quarantines NaN coordinate elements of pixcrd[] from infecting
            // non-NaN elements.
            img[i] += *piximg * temp;
          }
        }
      }

      pix += nelemn;
      img += nelem;
    }

  } else {
    // Distortions are present.
    size_t naxsiz = naxis * sizeof(double);
    double *tmp = calloc(naxis, sizeof(double));
    if (tmp == 0x0) {
      return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
    }

    for (int k = 0; k < ncoord; k++) {
      if (lin->dispre) {
        int status = disp2x(lin->dispre, pix, tmp);
        if (status) {
          return wcserr_set(LIN_ERRMSG(lin_diserr[status]));
        }
      } else {
        memcpy(tmp, pix, naxsiz);
      }

      if (lin->unity) {
        for (int i = 0; i < naxis; i++) {
          img[i] = tmp[i] - lin->crpix[i];
        }

      } else {
        for (int j = 0; j < naxis; j++) {
          tmp[j] -= lin->crpix[j];
        }

        double *piximg = lin->piximg;
        for (int i = 0; i < naxis; i++) {
          img[i] = 0.0;
          for (int j = 0; j < naxis; j++) {
            if (*piximg != 0.0) {
              // See comment above.
              img[i] += *piximg * tmp[j];
            }
            piximg++;
          }
        }
      }

      if (lin->disseq) {
        int status = disp2x(lin->disseq, img, tmp);
        if (status) {
          free(tmp);
          return wcserr_set(LIN_ERRMSG(lin_diserr[status]));
        }

        // With sequent distortions, cdelt is not incorporated into piximg...
        for (int i = 0; i < naxis; i++) {
          img[i] = lin->cdelt[i] * tmp[i];
        }

      } else if (lin->unity) {
        // ...nor if the matrix is unity.
        for (int i = 0; i < naxis; i++) {
          img[i] *= lin->cdelt[i];
        }
      }

      pix += nelem;
      img += nelem;
    }

    free(tmp);
  }

  return 0;
}

//----------------------------------------------------------------------------

int linx2p(
  struct linprm *lin,
  int ncoord,
  int nelem,
  const double imgcrd[],
  double pixcrd[])

{
  static const char *function = "linx2p";

  int status = 0;

  // Initialize.
  if (lin == 0x0) return LINERR_NULL_POINTER;
  struct wcserr **err = &(lin->err);

  if (abs(lin->flag) != LINSET) {
    if ((status = linset(lin))) {
      return status;
    }
  }

  int naxis = lin->naxis;


  // Convert intermediate world coordinates to pixel coordinates.
  const double *img = imgcrd;
  double *pix = pixcrd;

  if (lin->simple) {
    // Handle the simplest and most common case with maximum efficiency.
    int nelemn = nelem - naxis;
    for (int k = 0; k < ncoord; k++) {
      for (int j = 0; j < naxis; j++) {
        *(pix++) = (*(img++) / lin->cdelt[j]) + lin->crpix[j];
      }

      img += nelemn;
      pix += nelemn;
    }

  } else if (lin->affine) {
    // No distortions.
    int nelemn = nelem - naxis;
    for (int k = 0; k < ncoord; k++) {
      // cdelt will have been incorporated into imgpix.
      double *imgpix = lin->imgpix;

      for (int j = 0; j < naxis; j++) {
        *pix = 0.0;
        for (int i = 0; i < naxis; i++) {
          if (*imgpix != 0.0) {
            // Skipped if *imgpix == 0.0 in case img[i] is NaN, noting that
            // zero * NaN = NaN.  Thus, if the PCij matrix is diagonal, this
            // quarantines NaN coordinate elements of imgcrd[] from infecting
            // non-NaN elements.
            *pix += *imgpix * img[i];
          }
          imgpix++;
        }

        *(pix++) += lin->crpix[j];
      }

      img += nelem;
      pix += nelemn;
    }

  } else {
    // Distortions are present.
    size_t naxsiz = naxis * sizeof(double);
    double *tmp = calloc(naxis, sizeof(double));
    if (tmp == 0x0) {
      return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
    }

    for (int k = 0; k < ncoord; k++) {
      if (lin->disseq) {
        // With sequent distortions, cdelt is not incorporated into imgpix...
        for (int i = 0; i < naxis; i++) {
          tmp[i] = img[i] / lin->cdelt[i];
        }

        if ((status = disx2p(lin->disseq, tmp, pix))) {
          free(tmp);
          return wcserr_set(LIN_ERRMSG(lin_diserr[status]));
        }

        memcpy(tmp, pix, naxsiz);

      } else if (lin->unity) {
        // ...nor if the matrix is unity.
        for (int i = 0; i < naxis; i++) {
          tmp[i] = img[i] / lin->cdelt[i];
        }

      } else {
        // cdelt will have been incorporated into imgpix.
        memcpy(tmp, img, naxsiz);
      }

      if (lin->unity) {
        for (int j = 0; j < naxis; j++) {
          pix[j] = tmp[j] + lin->crpix[j];
        }

      } else {
        double *imgpix = lin->imgpix;
        for (int j = 0; j < naxis; j++) {
          pix[j] = lin->crpix[j];
          for (int i = 0; i < naxis; i++) {
            if (*imgpix != 0.0) {
              // See comment above.
              pix[j] += *imgpix * tmp[i];
            }
            imgpix++;
          }
        }
      }

      if (lin->dispre) {
        memcpy(tmp, pix, naxsiz);

        if ((status = disx2p(lin->dispre, tmp, pix))) {
          free(tmp);
          return wcserr_set(LIN_ERRMSG(lin_diserr[status]));
        }
      }

      img += nelem;
      pix += nelem;
    }

    free(tmp);
  }

  return 0;
}

//----------------------------------------------------------------------------

int linwarp(
  struct linprm *lin,
  const double pixblc[],
  const double pixtrc[],
  const double pixsamp[],
  int    *nsamp,
  double maxdis[],
  double *maxtot,
  double avgdis[],
  double *avgtot,
  double rmsdis[],
  double *rmstot)

{
  static const char *function = "linwarp";

  // Initialize.
  if (lin == 0x0) return LINERR_NULL_POINTER;
  struct wcserr **err = &(lin->err);

  int naxis = lin->naxis;

  if (nsamp) *nsamp = 0;
  for (int j = 0; j < naxis; j++) {
    if (maxdis) maxdis[j] = 0.0;
    if (avgdis) avgdis[j] = 0.0;
    if (rmsdis) rmsdis[j] = 0.0;
  }
  if (maxtot) *maxtot = 0.0;
  if (avgtot) *avgtot = 0.0;
  if (rmstot) *rmstot = 0.0;

  // Quick return if no distortions.
  if (lin->affine) return 0;

  int status = 0;

  // It's easier if there are no sequent distortions!
  if (lin->disseq == 0x0) {
    status = diswarp(lin->dispre, pixblc, pixtrc, pixsamp, nsamp, maxdis,
                     maxtot, avgdis, avgtot, rmsdis, rmstot);
    return wcserr_set(LIN_ERRMSG(lin_diserr[status]));
  }

  // Make a reference copy of lin without distortions.
  double *pixinc = 0x0;
  double *pix0   = 0x0;
  struct linprm affine;
  affine.flag = -1;

  status = lincpy(1, lin, &affine) ||
           lindist(1, &affine, 0x0, 0) ||
           lindist(2, &affine, 0x0, 0) ||
           linset(&affine);
  if (status) {
    wcserr_set(LIN_ERRMSG(status));
    goto cleanup;
  }

  // Work out increments on each axis.
  int ncoord = 0;
  if ((pixinc = calloc(naxis, sizeof(double))) == 0x0) { 
    wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
    goto cleanup;
  }

  for (int j = 0; j < naxis; j++) {
    double pixspan = pixtrc[j] - (pixblc ? pixblc[j] : 1.0);

    if (pixsamp == 0x0) {
      pixinc[j] = 1.0;
    } else {
      if (pixsamp[j] == 0.0) {
        pixinc[j] = 1.0;
      } else if (pixsamp[j] > 0.0) {
        pixinc[j] = pixsamp[j];
      } else if (pixsamp[j] > -1.5) {
        pixinc[j] = 2.0*pixspan;
      } else {
        pixinc[j] = pixspan / ((int)(-pixsamp[j] - 0.5));
      }
    }

    if (j == 0) {
      // Number of samples on axis 1.
      ncoord = 1 + (int)((pixspan/pixinc[0]) + 0.5);
    }
  }

  // Allocate memory in bulk for processing the image row by row.
  size_t naxcrd = (size_t)naxis * (size_t)ncoord;
  size_t nelem = 3*(naxcrd + naxis);
  if ((pix0 = calloc(nelem, sizeof(double))) == 0x0) {
    status = wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
    goto cleanup;
  }

  // Carve up the allocated memory.
  double *img    = pix0 + naxcrd;
  double *pix1   = img  + naxcrd;
  double *pixend = pix1 + naxcrd;
  double *sumdis = pixend + naxis;
  double *ssqdis = sumdis + naxis;


  // Set up the array of pixel coordinates.
  for (int j = 0; j < naxis; j++) {
    pix0[j] = pixblc ? pixblc[j] : 1.0;
    pixend[j] = pixtrc[j] + 0.5*pixinc[j];
  }

  double *pix0p = pix0 + naxis;
  for (int i = 1; i < ncoord; i++) {
    *(pix0p++) = pix0[0] + i*pixinc[0];

    for (int j = 1; j < naxis; j++) {
      *(pix0p++) = pix0[j];
    }
  }

  // Initialize accumulators.
  for (int j = 0; j < naxis; j++) {
    sumdis[j] = 0.0;
    ssqdis[j] = 0.0;
  }
  double sumtot = 0.0;
  double ssqtot = 0.0;


  // Loop over N dimensions.
  int carry = 0;
  while (carry == 0) {
    if ((status = linp2x(lin, ncoord, naxis, pix0, img))) {
      // (Preserve the error message set by linp2x().)
      goto cleanup;
    }

    if ((status = linx2p(&affine, ncoord, naxis, img, pix1))) {
      // (Preserve the error message set by linx2p().)
      goto cleanup;
    }

    // Accumulate statistics.
    double *pix0p = pix0;
    double *pix1p = pix1;
    for (int i = 0; i < ncoord; i++) {
      (*nsamp)++;

      double dssq = 0.0;
      for (int j = 0; j < naxis; j++) {
        double dpix = *(pix1p++) - *(pix0p++);
        double dpx2 = dpix*dpix;

        sumdis[j] += dpix;
        ssqdis[j] += dpx2;

        if (maxdis && (dpix = fabs(dpix)) > maxdis[j]) maxdis[j] = dpix;

        dssq += dpx2;
      }

      double totdis = sqrt(dssq);
      sumtot += totdis;
      ssqtot += totdis*totdis;

      if (maxtot && *maxtot < totdis) *maxtot = totdis;
    }

    // Next array of pixel coordinates.
    for (int j = 1; j < naxis; j++) {
      pix0[j] += pixinc[j];
      if ((carry = (pix0[j] > pixend[j]))) {
        pix0[j] = pixblc ? pixblc[j] : 1.0;
      }

      pix0p = pix0 + naxis + j;
      for (int i = 1; i < ncoord; i++) {
        *pix0p = pix0[j];
        pix0p += naxis;
      }

      if (carry == 0) break;
    }
  }


  // Compute the means and RMSs.
  for (int j = 0; j < naxis; j++) {
    ssqdis[j] /= *nsamp;
    sumdis[j] /= *nsamp;
    if (avgdis) avgdis[j] = sumdis[j];
    if (rmsdis) rmsdis[j] = sqrt(ssqdis[j] - sumdis[j]*sumdis[j]);
  }

  ssqtot /= *nsamp;
  sumtot /= *nsamp;
  if (avgtot) *avgtot = sumtot;
  if (rmstot) *rmstot = sqrt(ssqtot - sumtot*sumtot);


cleanup:
  linfree(&affine);
  if (pixinc) free(pixinc);
  if (pix0) free(pix0);

  return status;
}

//----------------------------------------------------------------------------

int matinv(int n, const double mat[], double inv[])

{
  // To appease static code analysers.
  size_t nszt = n;

  // Allocate memory for internal arrays.
  int *mxl = calloc(nszt, sizeof(int));
  if (mxl == 0x0) {
    return LINERR_MEMORY;
  }

  int *lxm = calloc(nszt, sizeof(int));
  if (lxm == 0x0) {
    free(mxl);
    return LINERR_MEMORY;
  }

  double *rowmax = calloc(nszt, sizeof(double));
  if (rowmax == 0x0) {
    free(mxl);
    free(lxm);
    return LINERR_MEMORY;
  }

  double *lu = calloc(nszt*nszt, sizeof(double));
  if (lu == 0x0) {
    free(mxl);
    free(lxm);
    free(rowmax);
    return LINERR_MEMORY;
  }


  // Initialize arrays.
  int ij = 0;
  for (int i = 0; i < n; i++) {
    // Vector that records row interchanges.
    mxl[i] = i;

    rowmax[i] = 0.0;

    for (int j = 0; j < n; j++, ij++) {
      double dtemp = fabs(mat[ij]);
      if (dtemp > rowmax[i]) rowmax[i] = dtemp;

      lu[ij] = mat[ij];
    }

    // A row of zeroes indicates a singular matrix.
    if (rowmax[i] == 0.0) {
      free(mxl);
      free(lxm);
      free(rowmax);
      free(lu);
      return LINERR_SINGULAR_MTX;
    }
  }


  // Form the LU triangular factorization using scaled partial pivoting.
  for (int k = 0; k < n; k++) {
    // Decide whether to pivot.
    int pivot = k;
    double colmax = fabs(lu[k*n+k]) / rowmax[k];

    for (int i = k+1; i < n; i++) {
      int ik = i*n + k;
      double dtemp = fabs(lu[ik]) / rowmax[i];
      if (dtemp > colmax) {
        colmax = dtemp;
        pivot = i;
      }
    }

    if (pivot > k) {
      // We must pivot, interchange the rows of the design matrix.
      int kj = k*n;
      int pj = pivot*n;
      for (int j = 0; j < n; j++, pj++, kj++) {
        double dtemp = lu[pj];
        lu[pj] = lu[kj];
        lu[kj] = dtemp;
      }

      // Amend the vector of row maxima.
      double dtemp = rowmax[pivot];
      rowmax[pivot] = rowmax[k];
      rowmax[k] = dtemp;

      // Record the interchange for later use.
      int itemp = mxl[pivot];
      mxl[pivot] = mxl[k];
      mxl[k] = itemp;
    }

    // Gaussian elimination.
    for (int i = k+1; i < n; i++) {
      int ik = i*n + k;

      // Nothing to do if lu[ik] is zero.
      if (lu[ik] != 0.0) {
        // Save the scaling factor.
        lu[ik] /= lu[k*n+k];

        // Subtract rows.
        for (int j = k+1; j < n; j++) {
          lu[i*n+j] -= lu[ik]*lu[k*n+j];
        }
      }
    }
  }


  // mxl[i] records which row of mat corresponds to row i of lu.
  // lxm[i] records which row of lu  corresponds to row i of mat.
  for (int i = 0; i < n; i++) {
    lxm[mxl[i]] = i;
  }


  // Determine the inverse matrix.
  ij = 0;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++, ij++) {
      inv[ij] = 0.0;
    }
  }

  for (int k = 0; k < n; k++) {
    inv[lxm[k]*n+k] = 1.0;

    // Forward substitution.
    for (int i = lxm[k]+1; i < n; i++) {
      for (int j = lxm[k]; j < i; j++) {
        inv[i*n+k] -= lu[i*n+j]*inv[j*n+k];
      }
    }

    // Backward substitution.
    for (int i = n-1; i >= 0; i--) {
      for (int j = i+1; j < n; j++) {
        inv[i*n+k] -= lu[i*n+j]*inv[j*n+k];
      }
      inv[i*n+k] /= lu[i*n+i];
    }
  }

  free(mxl);
  free(lxm);
  free(rowmax);
  free(lu);

  return 0;
}
@


8.6
log
@WCSLIB 8.6
@
text
@d2 1
a2 1
  WCSLIB 8.6 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: lin.c,v 8.5.1.3 2026/03/29 13:36:16 mcalabre Exp mcalabre $
d31 1
d41 1
d104 1
d106 1
a106 1
    return wcserr_set(WCSERR_SET(LINERR_MEMORY),
d110 5
d150 2
a151 1
        if ((lin->pc = calloc(naxis*naxis, sizeof(double))) == 0x0) {
d453 1
d456 1
a456 1
  sizes[1] += naxis * sizeof(double);
d459 1
a459 1
  sizes[1] += naxis*naxis * sizeof(double);
d462 1
a462 1
  sizes[1] += naxis * sizeof(double);
d483 1
a483 1
  sizes[1] += naxis*naxis * sizeof(double);
d486 1
a486 1
  sizes[1] += naxis*naxis * sizeof(double);
d714 2
a715 1
      if ((lin->piximg = calloc(naxis*naxis, sizeof(double))) == 0x0) {
d719 1
a719 1
      if ((lin->imgpix = calloc(naxis*naxis, sizeof(double))) == 0x0) {
d824 1
a824 1
    int ndbl   = naxis * sizeof(double);
d827 1
a827 1
      memset(img, 0, ndbl);
d852 1
a852 1
    int ndbl = naxis * sizeof(double);
d865 1
a865 1
        memcpy(tmp, pix, ndbl);
d992 1
a992 1
    int ndbl = naxis * sizeof(double);
d1010 1
a1010 1
        memcpy(tmp, pix, ndbl);
d1020 1
a1020 1
        memcpy(tmp, img, ndbl);
d1043 1
a1043 1
        memcpy(tmp, pix, ndbl);
a1133 6
    } else if (pixsamp[j] == 0.0) {
      pixinc[j] = 1.0;
    } else if (pixsamp[j] > 0.0) {
      pixinc[j] = pixsamp[j];
    } else if (pixsamp[j] > -1.5) {
      pixinc[j] = 2.0*pixspan;
d1135 9
a1143 1
      pixinc[j] = pixspan / ((int)(-pixsamp[j] - 0.5));
d1153 3
a1155 1
  if ((pix0 = calloc((3*ncoord+3)*naxis, sizeof(double))) == 0x0) {
d1161 3
a1163 3
  double *img    = pix0 + naxis*ncoord;
  double *pix1   = img  + naxis*ncoord;
  double *pixend = pix1 + naxis*ncoord;
d1276 3
d1280 1
a1280 1
  int *mxl = calloc(n, sizeof(int));
d1285 1
a1285 1
  int *lxm = calloc(n, sizeof(int));
d1291 1
a1291 1
  double *rowmax = calloc(n, sizeof(double));
d1298 1
a1298 1
  double *lu = calloc(n*n, sizeof(double));
@


8.6.1.1
log
@WCSLIB 8.6 development branch.
@
text
@d22 1
a22 1
  $Id: lin.c,v 8.6 2026/03/29 13:53:56 mcalabre Exp $
@


8.6.1.2
log
@Include wcslimits.h to get NAXMAX.  Added a new error code, LINERR_BAD_PARAM.
In lininit(), return LINERR_BAD_PARAM rather than LINERR_MEMORY if naxis is
negative.
Inconsequential change prompted by clang-tidy:
 - In lininit(), check that naxis does not exceed NAXMAX
   (bugprone-implicit-widening-of-multiplication-result).
@
text
@d22 1
a22 1
  $Id: lin.c,v 8.6.1.1 2026/03/29 14:19:26 mcalabre Exp mcalabre $
a30 1
#include "wcslimits.h"
a39 1
  "Invalid parameter value",
a101 1
  // Sanity check on naxis.
d103 1
a103 1
    return wcserr_set(WCSERR_SET(LINERR_BAD_PARAM),
a104 5
  }

  if (NAXMAX < naxis) {
    return wcserr_set(WCSERR_SET(LINERR_BAD_PARAM),
      "naxis exceeds %d (got %d)", NAXMAX, naxis);
@


8.6.1.3
log
@Inconsequential changes prompted by clang-tidy:
 - Explicitly cast return value of sizeof() to int when doing memory
   calculations (bugprone-narrowing-conversions).
 - Do memory size calculations in size_t
   (bugprone-implicit-widening-of-multiplication-result).
 - Restructured an if-block in linwarp() to disguise a repetition
   (bugprone-branch-clone).
@
text
@d22 1
a22 1
  $Id: lin.c,v 8.6.1.2 2026/04/05 08:25:58 mcalabre Exp mcalabre $
d150 1
a150 2
        size_t naxszt = naxis;
        if ((lin->pc = calloc(naxszt*naxszt, sizeof(double))) == 0x0) {
a451 1
  int naxsiz = naxis * (int)(sizeof(double));
d454 1
a454 1
  sizes[1] += naxsiz;
d457 1
a457 1
  sizes[1] += naxis*naxsiz;
d460 1
a460 1
  sizes[1] += naxsiz;
d481 1
a481 1
  sizes[1] += naxis*naxsiz;
d484 1
a484 1
  sizes[1] += naxis*naxsiz;
d712 1
a712 2
      size_t naxszt = naxis;
      if ((lin->piximg = calloc(naxszt*naxszt, sizeof(double))) == 0x0) {
d716 1
a716 1
      if ((lin->imgpix = calloc(naxszt*naxszt, sizeof(double))) == 0x0) {
d821 1
a821 1
    size_t naxsiz = naxis * sizeof(double);
d824 1
a824 1
      memset(img, 0, naxsiz);
d849 1
a849 1
    size_t naxsiz = naxis * sizeof(double);
d862 1
a862 1
        memcpy(tmp, pix, naxsiz);
d989 1
a989 1
    size_t naxsiz = naxis * sizeof(double);
d1007 1
a1007 1
        memcpy(tmp, pix, naxsiz);
d1017 1
a1017 1
        memcpy(tmp, img, naxsiz);
d1040 1
a1040 1
        memcpy(tmp, pix, naxsiz);
d1131 6
d1138 1
a1138 9
      if (pixsamp[j] == 0.0) {
        pixinc[j] = 1.0;
      } else if (pixsamp[j] > 0.0) {
        pixinc[j] = pixsamp[j];
      } else if (pixsamp[j] > -1.5) {
        pixinc[j] = 2.0*pixspan;
      } else {
        pixinc[j] = pixspan / ((int)(-pixsamp[j] - 0.5));
      }
d1148 1
a1148 3
  size_t naxcrd = (size_t)naxis * (size_t)ncoord;
  size_t nelem = 3*(naxcrd + naxis);
  if ((pix0 = calloc(nelem, sizeof(double))) == 0x0) {
d1154 3
a1156 3
  double *img    = pix0 + naxcrd;
  double *pix1   = img  + naxcrd;
  double *pixend = pix1 + naxcrd;
a1268 3
  // To appease static code analysers.
  size_t nszt = n;

d1270 1
a1270 1
  int *mxl = calloc(nszt, sizeof(int));
d1275 1
a1275 1
  int *lxm = calloc(nszt, sizeof(int));
d1281 1
a1281 1
  double *rowmax = calloc(nszt, sizeof(double));
d1288 1
a1288 1
  double *lu = calloc(nszt*nszt, sizeof(double));
@


8.5
log
@WCSLIB 8.5
@
text
@d2 2
a3 2
  WCSLIB 8.5 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2025, Mark Calabretta
d21 2
a22 2
  http://www.atnf.csiro.au/people/Mark.Calabretta
  $Id: lin.c,v 8.4.1.3 2025/12/06 13:37:15 mcalabre Exp mcalabre $
d995 2
a996 2
          wcserr_set(LIN_ERRMSG(lin_diserr[status]));
          goto cleanup;
d1035 2
a1036 2
          wcserr_set(LIN_ERRMSG(lin_diserr[status]));
          goto cleanup;
a1043 1
    cleanup:
d1047 1
a1047 1
  return status;
@


8.5.1.1
log
@WCSLIB 8.5 development branch.
@
text
@d22 1
a22 1
  $Id: lin.c,v 8.5 2025/12/06 13:47:41 mcalabre Exp $
@


8.5.1.2
log
@In linx2p(), replaced two instances of goto to work around an apparent
compiler bug.
@
text
@d21 2
a22 2
  http://www.atnf.csiro.au/computing/software/wcs
  $Id: lin.c,v 8.5.1.1 2025/12/06 14:05:15 mcalabre Exp mcalabre $
d995 2
a996 2
          free(tmp);
          return wcserr_set(LIN_ERRMSG(lin_diserr[status]));
d1035 2
a1036 2
          free(tmp);
          return wcserr_set(LIN_ERRMSG(lin_diserr[status]));
d1044 1
d1048 1
a1048 1
  return 0;
@


8.5.1.3
log
@Updated date in copyright notice.
@
text
@d3 1
a3 1
  Copyright (C) 1995-2026, Mark Calabretta
d22 1
a22 1
  $Id: lin.c,v 8.5.1.2 2026/03/26 12:24:05 mcalabre Exp mcalabre $
@


8.4
log
@WCSLIB 8.4
@
text
@d2 2
a3 2
  WCSLIB 8.4 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2024, Mark Calabretta
d22 1
a22 1
  $Id: lin.c,v 8.3.1.2 2024/07/09 08:49:16 mcalabre Exp mcalabre $
d825 7
a831 1
          img[i] += *piximg * temp;
d871 5
a875 1
            img[i] += *(piximg++) * tmp[j];
d883 1
a883 1
	  free(tmp);
d962 7
a968 1
          *pix += *imgpix * img[i];
d1022 5
a1026 1
            pix[j] += *(imgpix++) * tmp[i];
@


8.4.1.1
log
@WCSLIB 8.4 development branch.
@
text
@d22 1
a22 1
  $Id: lin.c,v 8.4 2024/10/28 13:56:16 mcalabre Exp $
@


8.4.1.2
log
@In linp2x(), quarantine NaN elements of the pixel coordinate vector from
infecting non-NaN elements in the case where the PCij matrix is diagonal
(noting that zero * NaN = NaN).  Likewise in linx2p().
@
text
@d22 1
a22 1
  $Id: lin.c,v 8.4.1.1 2024/10/28 13:58:41 mcalabre Exp mcalabre $
d825 1
a825 7
          if (*piximg != 0.0) {
            // Skipped if *piximg == 0.0 in case temp is NaN, noting that
            // zero * NaN = NaN.  Thus, if the PCij matrix is diagonal, this
            // quarantines NaN coordinate elements of pixcrd[] from infecting
            // non-NaN elements.
            img[i] += *piximg * temp;
          }
d865 1
a865 5
            if (*piximg != 0.0) {
              // See comment above.
              img[i] += *piximg * tmp[j];
            }
            piximg++;
d873 1
a873 1
          free(tmp);
d952 1
a952 7
          if (*imgpix != 0.0) {
            // Skipped if *imgpix == 0.0 in case img[i] is NaN, noting that
            // zero * NaN = NaN.  Thus, if the PCij matrix is diagonal, this
            // quarantines NaN coordinate elements of imgcrd[] from infecting
            // non-NaN elements.
            *pix += *imgpix * img[i];
          }
d1006 1
a1006 5
            if (*imgpix != 0.0) {
              // See comment above.
              pix[j] += *imgpix * tmp[i];
            }
            imgpix++;
@


8.4.1.3
log
@Updated date in copyright notice.
@
text
@d3 1
a3 1
  Copyright (C) 1995-2025, Mark Calabretta
d22 1
a22 1
  $Id: lin.c,v 8.4.1.2 2025/10/12 12:50:05 mcalabre Exp mcalabre $
@


8.3
log
@WCSLIB 8.3
@
text
@d2 1
a2 1
  WCSLIB 8.3 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: lin.c,v 8.2.1.8 2024/05/13 05:05:56 mcalabre Exp mcalabre $
d90 1
a90 1
      lin->tmpcrd = 0x0;
a185 1
    if (lin->tmpcrd) free(lin->tmpcrd);
a193 1
  lin->tmpcrd  = 0x0;
a404 1
    if (lin->tmpcrd) free(lin->tmpcrd);
a419 2
  lin->tmpcrd   = 0x0;

a477 3
  // linprm::tmpcrd[].
  sizes[1] += naxis * sizeof(double);

a593 3
  // Work arrays.
  WCSPRINTF_PTR("     tmpcrd: ", lin->tmpcrd, "\n");

a763 9

  // Create work arrays.
  if (lin->tmpcrd) free(lin->tmpcrd);
  if ((lin->tmpcrd = calloc(naxis, sizeof(double))) == 0x0) {
    linfree(lin);
    return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
  }


d836 4
a839 1
    double *tmp  = lin->tmpcrd;
d873 1
d892 2
d911 2
d918 1
a918 2
    int status = linset(lin);
    if (status) {
d966 4
a969 1
    double *tmp  = lin->tmpcrd;
d978 3
a980 3
        int status = disx2p(lin->disseq, tmp, pix);
        if (status) {
          return wcserr_set(LIN_ERRMSG(lin_diserr[status]));
d1014 3
a1016 3
        int status = disx2p(lin->dispre, tmp, pix);
        if (status) {
          return wcserr_set(LIN_ERRMSG(lin_diserr[status]));
d1023 3
d1028 1
a1028 1
  return 0;
d1068 2
d1072 2
a1073 2
    int status = diswarp(lin->dispre, pixblc, pixtrc, pixsamp, nsamp,
                         maxdis, maxtot, avgdis, avgtot, rmsdis, rmstot);
d1078 2
d1083 4
a1086 4
  int status = lincpy(1, lin, &affine) ||
               lindist(1, &affine, 0x0, 0) ||
               lindist(2, &affine, 0x0, 0) ||
               linset(&affine);
d1088 2
a1089 1
    return wcserr_set(LIN_ERRMSG(status));
d1094 5
a1099 1
    double *pixinc = lin->tmpcrd;
d1121 3
a1123 3
  double *pix0 = calloc((3*ncoord+4)*naxis, sizeof(double));
  if (pix0 == 0x0) {
    return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
d1129 1
a1129 2
  double *pixinc = pix1 + naxis*ncoord;
  double *pixend = pixinc + naxis;
a1133 3
  // Copy tmpcrd since linp2x() will overwrite it.
  memcpy(pixinc, lin->tmpcrd, naxis*sizeof(double));

a1160 1
    int status;
d1231 2
a1232 1
  free(pix0);
@


8.3.1.1
log
@WCSLIB 8.3 development branch.
@
text
@d22 1
a22 1
  $Id: lin.c,v 8.3 2024/05/13 16:33:00 mcalabre Exp $
@


8.3.1.2
log
@Excise linprm::tmpcrd, it's not thread-safe!
@
text
@d22 1
a22 1
  $Id: lin.c,v 8.3.1.1 2024/05/13 16:35:39 mcalabre Exp mcalabre $
d90 1
a90 1
      lin->dummy  = 0x0;
d186 1
d195 1
d407 1
d423 2
d483 3
d602 3
d775 9
d856 1
a856 4
    double *tmp = calloc(naxis, sizeof(double));
    if (tmp == 0x0) {
      return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
    }
a889 1
	  free(tmp);
a907 2

    free(tmp);
a924 2
  int status = 0;

d930 2
a931 1
    if ((status = linset(lin))) {
d979 1
a979 4
    double *tmp = calloc(naxis, sizeof(double));
    if (tmp == 0x0) {
      return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
    }
d988 3
a990 3
        if ((status = disx2p(lin->disseq, tmp, pix))) {
          wcserr_set(LIN_ERRMSG(lin_diserr[status]));
          goto cleanup;
d1024 3
a1026 3
        if ((status = disx2p(lin->dispre, tmp, pix))) {
          wcserr_set(LIN_ERRMSG(lin_diserr[status]));
          goto cleanup;
a1032 3

    cleanup:
    free(tmp);
d1035 1
a1035 1
  return status;
a1074 2
  int status = 0;

d1077 2
a1078 2
    status = diswarp(lin->dispre, pixblc, pixtrc, pixsamp, nsamp, maxdis,
                     maxtot, avgdis, avgtot, rmsdis, rmstot);
a1082 2
  double *pixinc = 0x0;
  double *pix0   = 0x0;
d1086 4
a1089 4
  status = lincpy(1, lin, &affine) ||
           lindist(1, &affine, 0x0, 0) ||
           lindist(2, &affine, 0x0, 0) ||
           linset(&affine);
d1091 1
a1091 2
    wcserr_set(LIN_ERRMSG(status));
    goto cleanup;
a1095 5
  if ((pixinc = calloc(naxis, sizeof(double))) == 0x0) { 
    wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
    goto cleanup;
  }

d1097 1
d1119 3
a1121 3
  if ((pix0 = calloc((3*ncoord+3)*naxis, sizeof(double))) == 0x0) {
    status = wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
    goto cleanup;
d1127 2
a1128 1
  double *pixend = pix1 + naxis*ncoord;
d1133 3
d1163 1
d1234 1
a1234 2
  if (pixinc) free(pixinc);
  if (pix0) free(pix0);
@


8.2
log
@WCSLIB 8.2
@
text
@d2 2
a3 2
  WCSLIB 8.2 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2023, Mark Calabretta
d22 1
a22 1
  $Id: lin.c,v 8.1.1.1 2023/07/05 17:15:00 mcalabre Exp mcalabre $
a34 2
const int LINSET = 137;

d55 2
d183 1
a183 1
  if (lin->flag == LINSET) {
a197 1
  lin->flag  = 0;
a199 1

d223 1
d439 1
a439 1
    return LINERR_SUCCESS;
d473 2
a474 2
  if (lin->flag != LINSET) {
    return LINERR_SUCCESS;
d486 29
a514 1
  return LINERR_SUCCESS;
d524 1
a524 1
  if (lin->flag != LINSET) {
a527 1
  wcsprintf("       flag: %d\n", lin->flag);
d530 1
d663 1
d689 1
a689 1
    if (lin->flag == LINSET) {
d707 2
a708 2
    if (lin->flag != LINSET || lin->i_naxis < naxis) {
      if (lin->flag == LINSET) {
d754 1
d764 1
d784 1
a784 1
  lin->flag = LINSET;
d805 1
a805 1
  if (lin->flag != LINSET) {
d816 2
a817 2
  register const double *pix = pixcrd;
  register double *img = imgcrd;
d840 1
a840 1
        register double *piximg = lin->piximg + j;
d856 1
a856 1
    register double *tmp  = lin->tmpcrd;
d878 1
a878 1
        register double *piximg = lin->piximg;
d929 1
a929 1
  if (lin->flag != LINSET) {
d940 2
a941 2
  register const double *img = imgcrd;
  register double *pix = pixcrd;
d960 1
a960 1
      register double *imgpix = lin->imgpix;
d979 1
a979 1
    register double *tmp  = lin->tmpcrd;
d1012 1
a1012 1
        register double *imgpix = lin->imgpix;
d1273 1
a1273 1
  register int ij = 0;
d1305 1
a1305 1
      register int ik = i*n + k;
d1315 2
a1316 2
      register int kj = k*n;
      register int pj = pivot*n;
d1336 1
a1336 1
      register int ik = i*n + k;
@


8.2.1.1
log
@WCSLIB 8.2 development branch.
@
text
@d22 1
a22 1
  $Id: lin.c,v 8.2 2023/11/16 10:00:29 mcalabre Exp $
@


8.2.1.2
log
@Declared LINSET to be static.
@
text
@d22 1
a22 1
  $Id: lin.c,v 8.2.1.1 2023/11/16 10:05:57 mcalabre Exp mcalabre $
d35 2
a55 2

static const int LINSET = 137;
@


8.2.1.3
log
@Updated date in copyright notice.
@
text
@d3 1
a3 1
  Copyright (C) 1995-2024, Mark Calabretta
d22 1
a22 1
  $Id: lin.c,v 8.2.1.2 2023/11/29 07:36:19 mcalabre Exp mcalabre $
@


8.2.1.4
log
@Changes required to support bypass mode in linset().
@
text
@d22 1
a22 1
  $Id: lin.c,v 8.2.1.3 2024/04/02 14:01:58 mcalabre Exp mcalabre $
d183 1
a183 1
  if (abs(lin->flag) == LINSET) {
d198 1
d201 1
a224 1
  lin->flag = 0;
d440 1
a440 1
    return 0;
d474 2
a475 2
  if (abs(lin->flag) != LINSET) {
    return 0;
d487 1
a487 1
  return 0;
d497 1
a497 1
  if (abs(lin->flag) != LINSET) {
d501 1
a503 1
  wcsprintf("       flag: %d\n", lin->flag);
a635 1
  if (lin->flag == -LINSET) return 0;
d661 1
a661 1
    if (abs(lin->flag) == LINSET) {
d679 2
a680 2
    if (abs(lin->flag) != LINSET || lin->i_naxis < naxis) {
      if (abs(lin->flag) == LINSET) {
d754 1
a754 1
  lin->flag = (lin->flag == 1) ? -LINSET : LINSET;
d775 1
a775 1
  if (abs(lin->flag) != LINSET) {
d786 2
a787 2
  const double *pix = pixcrd;
  double *img = imgcrd;
d810 1
a810 1
        double *piximg = lin->piximg + j;
d826 1
a826 1
    double *tmp  = lin->tmpcrd;
d848 1
a848 1
        double *piximg = lin->piximg;
d899 1
a899 1
  if (abs(lin->flag) != LINSET) {
d910 2
a911 2
  const double *img = imgcrd;
  double *pix = pixcrd;
d930 1
a930 1
      double *imgpix = lin->imgpix;
d949 1
a949 1
    double *tmp  = lin->tmpcrd;
d982 1
a982 1
        double *imgpix = lin->imgpix;
d1243 1
a1243 1
  int ij = 0;
d1275 1
a1275 1
      int ik = i*n + k;
d1285 2
a1286 2
      int kj = k*n;
      int pj = pivot*n;
d1306 1
a1306 1
      int ik = i*n + k;
@


8.2.1.5
log
@Added linenq().
@
text
@d22 1
a22 1
  $Id: lin.c,v 8.2.1.4 2024/05/08 08:52:30 mcalabre Exp mcalabre $
a486 30
}

//----------------------------------------------------------------------------

int linenq(const struct linprm *lin, int enquiry)

{
  static const char *function = "linenq";

  // Initialize.
  if (lin == 0x0) return LINERR_NULL_POINTER;

  int answer = 0;

  if (enquiry & LINENQ_MEM) {
    if (lin->m_flag != LINSET) return 0;
    answer = 1;
  }

  if (enquiry & LINENQ_SET) {
    if (abs(lin->flag) != LINSET) return 0;
    answer = 1;
  }

  if (enquiry & LINENQ_BYP) {
    if (lin->flag != -LINSET) return 0;
    answer = 1;
  }

  return answer;
@


8.2.1.6
log
@Attended to compiler warnings about unused variables.
@
text
@d22 1
a22 1
  $Id: lin.c,v 8.2.1.5 2024/05/08 15:14:26 mcalabre Exp mcalabre $
d494 2
@


8.2.1.7
log
@In linenq(), the linprm struct is also in bypass mode, though unset, if
linprm::flag == 1.
@
text
@d22 1
a22 1
  $Id: lin.c,v 8.2.1.6 2024/05/08 15:39:34 mcalabre Exp mcalabre $
d510 1
a510 1
    if (lin->flag != 1 && lin->flag != -LINSET) return 0;
@


8.2.1.8
log
@In linset(), set (lin->dispre)->flag = 0 explicitly before calling disset(),
and likewise (lin->disseq)->flag, as a safety measure to protect against
disprm in bypass mode.
@
text
@d22 1
a22 1
  $Id: lin.c,v 8.2.1.7 2024/05/10 14:32:14 mcalabre Exp mcalabre $
a753 1
    (lin->dispre)->flag = 0;
a762 1
    (lin->disseq)->flag = 0;
@


8.1
log
@WCSLIB 8.1
@
text
@d2 1
a2 1
  WCSLIB 8.1 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: lin.c,v 8.0.1.1 2023/07/01 06:22:44 mcalabre Exp mcalabre $
@


8.1.1.1
log
@WCSLIB 8.1 development branch.
@
text
@d22 1
a22 1
  $Id: lin.c,v 8.1 2023/07/05 17:12:07 mcalabre Exp $
@


8.0
log
@WCSLIB 8.0
@
text
@d2 1
a2 1
  WCSLIB 8.0 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: lin.c,v 7.13.1.2 2023/06/15 04:17:19 mcalabre Exp mcalabre $
@


8.0.1.1
log
@WCSLIB 8.0 development branch.
@
text
@d22 1
a22 1
  $Id: lin.c,v 8.0 2023/07/01 06:15:04 mcalabre Exp $
@


7.13
log
@WCSLIB 7.13
@
text
@d2 2
a3 2
  WCSLIB 7.13 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2022, Mark Calabretta
d22 1
a22 1
  $Id: lin.c,v 7.12.1.1 2022/09/09 05:00:36 mcalabre Exp mcalabre $
@


7.13.1.1
log
@WCSLIB 7.13 development branch.
@
text
@d22 1
a22 1
  $Id: lin.c,v 7.13 2022/10/07 03:43:35 mcalabre Exp $
@


7.13.1.2
log
@Updated date in copyright notice.
@
text
@d3 1
a3 1
  Copyright (C) 1995-2023, Mark Calabretta
d22 1
a22 1
  $Id: lin.c,v 7.13.1.1 2022/10/07 03:45:47 mcalabre Exp mcalabre $
@


7.12
log
@WCSLIB 7.12
@
text
@d2 1
a2 1
  WCSLIB 7.12 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: lin.c,v 7.11.1.1 2022/04/26 06:15:32 mcalabre Exp mcalabre $
@


7.12.1.1
log
@WCSLIB 7.12 development branch.
@
text
@d22 1
a22 1
  $Id: lin.c,v 7.12 2022/09/09 04:57:58 mcalabre Exp $
@


7.11
log
@WCSLIB 7.11
@
text
@d2 1
a2 1
  WCSLIB 7.11 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: lin.c,v 7.10.1.1 2022/04/23 14:26:54 mcalabre Exp mcalabre $
@


7.11.1.1
log
@WCSLIB 7.11 development branch.
@
text
@d22 1
a22 1
  $Id: lin.c,v 7.11 2022/04/26 06:13:52 mcalabre Exp $
@


7.10
log
@WCSLIB 7.10
@
text
@d2 1
a2 1
  WCSLIB 7.10 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: lin.c,v 7.9.1.1 2022/03/25 15:16:40 mcalabre Exp mcalabre $
@


7.10.1.1
log
@WCSLIB 7.10 development branch.
@
text
@d22 1
a22 1
  $Id: lin.c,v 7.10 2022/04/23 14:25:15 mcalabre Exp $
@


7.9
log
@WCSLIB 7.9
@
text
@d2 1
a2 1
  WCSLIB 7.9 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: lin.c,v 7.8.1.1 2022/03/25 06:14:14 mcalabre Exp mcalabre $
@


7.9.1.1
log
@WCSLIB 7.9 development branch.
@
text
@d22 1
a22 1
  $Id: lin.c,v 7.9 2022/03/25 15:14:48 mcalabre Exp $
@


7.8
log
@WCSLIB 7.8
@
text
@d2 1
a2 1
  WCSLIB 7.8 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: lin.c,v 7.7.1.2 2022/03/25 06:05:59 mcalabre Exp mcalabre $
@


7.8.1.1
log
@WCSLIB 7.8 development branch.
@
text
@d22 1
a22 1
  $Id: lin.c,v 7.8 2022/03/25 06:11:49 mcalabre Exp $
@


7.7
log
@WCSLIB 7.7
@
text
@d2 2
a3 2
  WCSLIB 7.7 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2021, Mark Calabretta
d22 1
a22 1
  $Id: lin.c,v 7.6.1.4 2021/07/02 08:07:37 mcalabre Exp mcalabre $
@


7.7.1.1
log
@WCSLIB 7.7 development branch.
@
text
@d22 1
a22 1
  $Id: lin.c,v 7.7 2021/07/12 06:36:49 mcalabre Exp $
@


7.7.1.2
log
@Updated date in copyright notice.
@
text
@d3 1
a3 1
  Copyright (C) 1995-2022, Mark Calabretta
d22 1
a22 1
  $Id: lin.c,v 7.7.1.1 2021/07/12 06:38:27 mcalabre Exp mcalabre $
@


7.6
log
@WCSLIB 7.6
@
text
@d2 1
a2 1
  WCSLIB 7.6 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: lin.c,v 7.5.1.2 2021/04/13 09:20:16 mcalabre Exp mcalabre $
a74 4
  int i, j;
  double *pc;
  struct wcserr **err;

d81 1
a81 1
  err = &(lin->err);
d203 1
a203 1
  for (j = 0; j < naxis; j++) {
d208 3
a210 3
  pc = lin->pc;
  for (i = 0; i < naxis; i++) {
    for (j = 0; j < naxis; j++) {
d221 1
a221 1
  for (i = 0; i < naxis; i++) {
a243 3
  int status;
  struct wcserr **err;

d245 1
a245 1
  err = &(lin->err);
d273 2
a274 1
    if ((status = disinit(1, lin->naxis, dis, ndpmax))) {
a288 5
  int i, j, naxis, status;
  const double *srcp;
  double *dstp;
  struct wcserr **err;

d291 1
a291 1
  err = &(lindst->err);
d293 1
a293 1
  naxis = linsrc->naxis;
d299 2
a300 1
  if ((status = lininit(alloc, naxis, lindst, 0))) {
d304 3
a306 3
  srcp = linsrc->crpix;
  dstp = lindst->crpix;
  for (j = 0; j < naxis; j++) {
d312 2
a313 2
  for (i = 0; i < naxis; i++) {
    for (j = 0; j < naxis; j++) {
d320 1
a320 1
  for (i = 0; i < naxis; i++) {
a437 1

a448 1
  int exsizes[2];
d461 1
d463 1
a463 1
  sizes[2] += exsizes[0] + exsizes[1];
d467 1
a467 1
  sizes[2] += exsizes[0] + exsizes[1];
a494 2
  int i, j, k;

d508 1
a508 1
  for (j = 0; j < lin->naxis; j++) {
d513 1
a513 1
  k = 0;
d515 1
a515 1
  for (i = 0; i < lin->naxis; i++) {
d517 1
a517 1
    for (j = 0; j < lin->naxis; j++) {
d525 1
a525 1
  for (i = 0; i < lin->naxis; i++) {
d541 2
a542 2
    k = 0;
    for (i = 0; i < lin->naxis; i++) {
d544 1
a544 1
      for (j = 0; j < lin->naxis; j++) {
d554 2
a555 2
    k = 0;
    for (i = 0; i < lin->naxis; i++) {
d557 1
a557 1
      for (j = 0; j < lin->naxis; j++) {
a634 4
  int i, j, naxis, status;
  double *pc, *piximg;
  struct wcserr **err;

d636 1
a636 1
  err = &(lin->err);
d638 1
a638 1
  naxis = lin->naxis;
d642 3
a644 3
  pc = lin->pc;
  for (i = 0; i < naxis; i++) {
    for (j = 0; j < naxis; j++) {
d672 1
a672 1
    for (i = 0; i < naxis; i++) {
d700 3
a702 3
    pc     = lin->pc;
    piximg = lin->piximg;
    for (i = 0; i < naxis; i++) {
d705 1
a705 1
        for (j = 0; j < naxis; j++) {
d709 1
a709 1
        for (j = 0; j < naxis; j++) {
d716 2
a717 1
    if ((status = matinv(naxis, lin->piximg, lin->imgpix))) {
d726 2
a727 1
    if ((status = disset(lin->dispre))) {
d735 2
a736 1
    if ((status = disset(lin->disseq))) {
a770 7
  int i, j, k, n, ndbl, nelemn, status;
  double temp;
  register const double *pix;
  register double *img, *piximg, *tmp;
  struct wcserr **err;


d773 1
a773 1
  err = &(lin->err);
d776 4
a779 1
    if ((status = linset(lin))) return status;
d782 1
a782 1
  n = lin->naxis;
d786 2
a787 2
  pix = pixcrd;
  img = imgcrd;
d791 3
a793 3
    nelemn = nelem - n;
    for (k = 0; k < ncoord; k++) {
      for (i = 0; i < n; i++) {
d803 3
a805 3
    ndbl   = n * sizeof(double);
    nelemn = nelem - n;
    for (k = 0; k < ncoord; k++) {
d808 1
a808 1
      for (j = 0; j < n; j++) {
d810 1
a810 1
        piximg = lin->piximg + j;
d813 2
a814 2
        temp = *(pix++) - lin->crpix[j];
        for (i = 0; i < n; i++, piximg += n) {
d825 2
a826 2
    ndbl = n * sizeof(double);
    tmp  = lin->tmpcrd;
d828 1
a828 1
    for (k = 0; k < ncoord; k++) {
d830 2
a831 1
        if ((status = disp2x(lin->dispre, pix, tmp))) {
d839 1
a839 1
        for (i = 0; i < n; i++) {
d844 1
a844 1
        for (j = 0; j < n; j++) {
d848 2
a849 2
        piximg = lin->piximg;
        for (i = 0; i < n; i++) {
d851 1
a851 1
          for (j = 0; j < n; j++) {
d858 2
a859 1
        if ((status = disp2x(lin->disseq, img, tmp))) {
d864 1
a864 1
        for (i = 0; i < n; i++) {
d870 1
a870 1
        for (i = 0; i < n; i++) {
a894 6
  int i, j, k, n, ndbl, nelemn, status;
  register const double *img;
  register double *imgpix, *pix, *tmp;
  struct wcserr **err;


d897 1
a897 1
  err = &(lin->err);
d900 4
a903 1
    if ((status = linset(lin))) return status;
d906 1
a906 1
  n = lin->naxis;
d910 2
a911 2
  img = imgcrd;
  pix = pixcrd;
d915 3
a917 3
    nelemn = nelem - n;
    for (k = 0; k < ncoord; k++) {
      for (j = 0; j < n; j++) {
d927 2
a928 2
    nelemn = nelem - n;
    for (k = 0; k < ncoord; k++) {
d930 1
a930 1
      imgpix = lin->imgpix;
d932 1
a932 1
      for (j = 0; j < n; j++) {
d934 1
a934 1
        for (i = 0; i < n; i++) {
d948 2
a949 2
    ndbl = n * sizeof(double);
    tmp  = lin->tmpcrd;
d951 1
a951 1
    for (k = 0; k < ncoord; k++) {
d954 1
a954 1
        for (i = 0; i < n; i++) {
d958 2
a959 1
        if ((status = disx2p(lin->disseq, tmp, pix))) {
d967 1
a967 1
        for (i = 0; i < n; i++) {
d977 1
a977 1
        for (j = 0; j < n; j++) {
d982 2
a983 2
        imgpix = lin->imgpix;
        for (j = 0; j < n; j++) {
d985 1
a985 1
          for (i = 0; i < n; i++) {
d994 2
a995 1
        if ((status = disx2p(lin->dispre, tmp, pix))) {
a1025 7
  int carry, i, j, naxis, ncoord, status = 0;
  double dpix, dpx2, dssq, *img, *pix0, *pix0p, *pix1, *pix1p, *pixend,
         *pixinc, pixspan, *ssqdis, ssqtot, *sumdis, sumtot, totdis;
  struct linprm affine;
  struct wcserr **err;


d1028 1
a1028 1
  err = &(lin->err);
d1030 1
a1030 1
  naxis = lin->naxis;
d1033 1
a1033 1
  for (j = 0; j < naxis; j++) {
d1047 2
a1048 2
    status = diswarp(lin->dispre, pixblc, pixtrc, pixsamp, nsamp,
                     maxdis, maxtot, avgdis, avgtot, rmsdis, rmstot);
d1053 1
d1055 6
a1060 4
  if ((status = (lincpy(1, lin, &affine) ||
                 lindist(1, &affine, 0x0, 0) ||
                 lindist(2, &affine, 0x0, 0) ||
                 linset(&affine)))) {
d1065 4
a1068 4
  pixinc = lin->tmpcrd;
  ncoord = 0;
  for (j = 0; j < naxis; j++) {
    pixspan = pixtrc[j] - (pixblc ? pixblc[j] : 1.0);
d1088 3
a1090 2
  // Get memory for processing the image row by row.
  if ((pix0 = calloc((3*ncoord+4)*naxis, sizeof(double))) == 0x0) {
d1094 7
a1100 6
  img    = pix0 + naxis*ncoord;
  pix1   = img  + naxis*ncoord;
  pixinc = pix1 + naxis*ncoord;
  pixend = pixinc + naxis;
  sumdis = pixend + naxis;
  ssqdis = sumdis + naxis;
d1107 1
a1107 1
  for (j = 0; j < naxis; j++) {
d1112 2
a1113 2
  pix0p = pix0 + naxis;
  for (i = 1; i < ncoord; i++) {
d1116 1
a1116 1
    for (j = 1; j < naxis; j++) {
d1122 1
a1122 1
  for (j = 0; j < naxis; j++) {
d1126 2
a1127 2
  sumtot = 0.0;
  ssqtot = 0.0;
d1131 1
a1131 1
  carry = 0;
d1133 1
d1145 3
a1147 3
    pix0p = pix0;
    pix1p = pix1;
    for (i = 0; i < ncoord; i++) {
d1150 4
a1153 4
      dssq = 0.0;
      for (j = 0; j < naxis; j++) {
        dpix = *(pix1p++) - *(pix0p++);
        dpx2 = dpix*dpix;
d1163 1
a1163 1
      totdis = sqrt(dssq);
d1171 1
a1171 1
    for (j = 1; j < naxis; j++) {
d1178 1
a1178 1
      for (i = 1; i < ncoord; i++) {
d1189 1
a1189 1
  for (j = 0; j < naxis; j++) {
a1213 5
  register int i, ij, ik, j, k, kj, pj;
  int    itemp, *mxl, *lxm, pivot;
  double colmax, *lu, *rowmax, dtemp;


d1215 2
a1216 1
  if ((mxl = calloc(n, sizeof(int))) == 0x0) {
d1219 3
a1221 1
  if ((lxm = calloc(n, sizeof(int))) == 0x0) {
d1226 2
a1227 1
  if ((rowmax = calloc(n, sizeof(double))) == 0x0) {
d1233 2
a1234 1
  if ((lu = calloc(n*n, sizeof(double))) == 0x0) {
d1243 2
a1244 1
  for (i = 0, ij = 0; i < n; i++) {
d1250 2
a1251 2
    for (j = 0; j < n; j++, ij++) {
      dtemp = fabs(mat[ij]);
d1269 1
a1269 1
  for (k = 0; k < n; k++) {
d1271 2
a1272 2
    colmax = fabs(lu[k*n+k]) / rowmax[k];
    pivot = k;
d1274 3
a1276 3
    for (i = k+1; i < n; i++) {
      ik = i*n + k;
      dtemp = fabs(lu[ik]) / rowmax[i];
d1285 4
a1288 2
      for (j = 0, pj = pivot*n, kj = k*n; j < n; j++, pj++, kj++) {
        dtemp = lu[pj];
d1294 1
a1294 1
      dtemp = rowmax[pivot];
d1299 1
a1299 1
      itemp = mxl[pivot];
d1305 2
a1306 2
    for (i = k+1; i < n; i++) {
      ik = i*n + k;
d1314 1
a1314 1
        for (j = k+1; j < n; j++) {
d1324 1
a1324 1
  for (i = 0; i < n; i++) {
d1330 3
a1332 2
  for (i = 0, ij = 0; i < n; i++) {
    for (j = 0; j < n; j++, ij++) {
d1337 1
a1337 1
  for (k = 0; k < n; k++) {
d1341 2
a1342 2
    for (i = lxm[k]+1; i < n; i++) {
      for (j = lxm[k]; j < i; j++) {
d1348 2
a1349 2
    for (i = n-1; i >= 0; i--) {
      for (j = i+1; j < n; j++) {
@


7.6.1.1
log
@WCSLIB 7.6 development branch.
@
text
@d22 1
a22 1
  $Id: lin.c,v 7.6 2021/04/13 12:57:01 mcalabre Exp $
@


7.6.1.2
log
@Converted to C99-style intermingled variable declarations.
@
text
@d22 1
a22 1
  $Id: lin.c,v 7.6.1.1 2021/04/13 13:00:35 mcalabre Exp mcalabre $
d75 4
d85 1
a85 1
  struct wcserr **err = &(lin->err);
d207 1
a207 1
  for (int j = 0; j < naxis; j++) {
d212 3
a214 3
  double *pc = lin->pc;
  for (int i = 0; i < naxis; i++) {
    for (int j = 0; j < naxis; j++) {
d225 1
a225 1
  for (int i = 0; i < naxis; i++) {
d248 3
d252 1
a252 1
  struct wcserr **err = &(lin->err);
d280 1
a280 2
    int status = disinit(1, lin->naxis, dis, ndpmax);
    if (status) {
d295 5
d302 1
a302 1
  struct wcserr **err = &(lindst->err);
d304 1
a304 1
  int naxis = linsrc->naxis;
d310 1
a310 2
  int status = lininit(alloc, naxis, lindst, 0);
  if (status) {
d314 3
a316 3
  const double *srcp = linsrc->crpix;
  double *dstp = lindst->crpix;
  for (int j = 0; j < naxis; j++) {
d322 2
a323 2
  for (int i = 0; i < naxis; i++) {
    for (int j = 0; j < naxis; j++) {
d330 1
a330 1
  for (int i = 0; i < naxis; i++) {
d448 1
d460 1
a472 1
  int exsizes[2];
d506 2
d521 1
a521 1
  for (int j = 0; j < lin->naxis; j++) {
d526 1
a526 1
  int k = 0;
d528 1
a528 1
  for (int i = 0; i < lin->naxis; i++) {
d530 1
a530 1
    for (int j = 0; j < lin->naxis; j++) {
d538 1
a538 1
  for (int i = 0; i < lin->naxis; i++) {
d554 2
a555 2
    int k = 0;
    for (int i = 0; i < lin->naxis; i++) {
d557 1
a557 1
      for (int j = 0; j < lin->naxis; j++) {
d567 2
a568 2
    int k = 0;
    for (int i = 0; i < lin->naxis; i++) {
d570 1
a570 1
      for (int j = 0; j < lin->naxis; j++) {
d648 4
d653 1
a653 1
  struct wcserr **err = &(lin->err);
d655 1
a655 1
  int naxis = lin->naxis;
d659 3
a661 3
  double *pc = lin->pc;
  for (int i = 0; i < naxis; i++) {
    for (int j = 0; j < naxis; j++) {
d689 1
a689 1
    for (int i = 0; i < naxis; i++) {
d717 3
a719 3
    pc = lin->pc;
    double *piximg = lin->piximg;
    for (int i = 0; i < naxis; i++) {
d722 1
a722 1
        for (int j = 0; j < naxis; j++) {
d726 1
a726 1
        for (int j = 0; j < naxis; j++) {
d733 1
a733 2
    int status = matinv(naxis, lin->piximg, lin->imgpix);
    if (status) {
d742 1
a742 2
    int status = disset(lin->dispre);
    if (status) {
d750 1
a750 2
    int status = disset(lin->disseq);
    if (status) {
d785 7
d794 1
a794 1
  struct wcserr **err = &(lin->err);
d797 1
a797 4
    int status = linset(lin);
    if (status) {
      return status;
    }
d800 1
a800 1
  int naxis = lin->naxis;
d804 2
a805 2
  register const double *pix = pixcrd;
  register double *img = imgcrd;
d809 3
a811 3
    int nelemn = nelem - naxis;
    for (int k = 0; k < ncoord; k++) {
      for (int i = 0; i < naxis; i++) {
d821 3
a823 3
    int ndbl   = naxis * sizeof(double);
    int nelemn = nelem - naxis;
    for (int k = 0; k < ncoord; k++) {
d826 1
a826 1
      for (int j = 0; j < naxis; j++) {
d828 1
a828 1
        register double *piximg = lin->piximg + j;
d831 2
a832 2
        double temp = *(pix++) - lin->crpix[j];
        for (int i = 0; i < naxis; i++, piximg += naxis) {
d843 2
a844 2
    int ndbl = naxis * sizeof(double);
    register double *tmp  = lin->tmpcrd;
d846 1
a846 1
    for (int k = 0; k < ncoord; k++) {
d848 1
a848 2
        int status = disp2x(lin->dispre, pix, tmp);
        if (status) {
d856 1
a856 1
        for (int i = 0; i < naxis; i++) {
d861 1
a861 1
        for (int j = 0; j < naxis; j++) {
d865 2
a866 2
        register double *piximg = lin->piximg;
        for (int i = 0; i < naxis; i++) {
d868 1
a868 1
          for (int j = 0; j < naxis; j++) {
d875 1
a875 2
        int status = disp2x(lin->disseq, img, tmp);
        if (status) {
d880 1
a880 1
        for (int i = 0; i < naxis; i++) {
d886 1
a886 1
        for (int i = 0; i < naxis; i++) {
d911 6
d919 1
a919 1
  struct wcserr **err = &(lin->err);
d922 1
a922 4
    int status = linset(lin);
    if (status) {
      return status;
    }
d925 1
a925 1
  int naxis = lin->naxis;
d929 2
a930 2
  register const double *img = imgcrd;
  register double *pix = pixcrd;
d934 3
a936 3
    int nelemn = nelem - naxis;
    for (int k = 0; k < ncoord; k++) {
      for (int j = 0; j < naxis; j++) {
d946 2
a947 2
    int nelemn = nelem - naxis;
    for (int k = 0; k < ncoord; k++) {
d949 1
a949 1
      register double *imgpix = lin->imgpix;
d951 1
a951 1
      for (int j = 0; j < naxis; j++) {
d953 1
a953 1
        for (int i = 0; i < naxis; i++) {
d967 2
a968 2
    int ndbl = naxis * sizeof(double);
    register double *tmp  = lin->tmpcrd;
d970 1
a970 1
    for (int k = 0; k < ncoord; k++) {
d973 1
a973 1
        for (int i = 0; i < naxis; i++) {
d977 1
a977 2
        int status = disx2p(lin->disseq, tmp, pix);
        if (status) {
d985 1
a985 1
        for (int i = 0; i < naxis; i++) {
d995 1
a995 1
        for (int j = 0; j < naxis; j++) {
d1000 2
a1001 2
        register double *imgpix = lin->imgpix;
        for (int j = 0; j < naxis; j++) {
d1003 1
a1003 1
          for (int i = 0; i < naxis; i++) {
d1012 1
a1012 2
        int status = disx2p(lin->dispre, tmp, pix);
        if (status) {
d1043 7
d1052 1
a1052 1
  struct wcserr **err = &(lin->err);
d1054 1
a1054 1
  int naxis = lin->naxis;
d1057 1
a1057 1
  for (int j = 0; j < naxis; j++) {
d1071 2
a1072 2
    int status = diswarp(lin->dispre, pixblc, pixtrc, pixsamp, nsamp,
                         maxdis, maxtot, avgdis, avgtot, rmsdis, rmstot);
a1076 1
  struct linprm affine;
d1078 4
a1081 5
  int status = (lincpy(1, lin, &affine) ||
                lindist(1, &affine, 0x0, 0) ||
                lindist(2, &affine, 0x0, 0) ||
                linset(&affine));
  if (status) {
d1086 4
a1089 4
  double *pixinc = lin->tmpcrd;
  int ncoord = 0;
  for (int j = 0; j < naxis; j++) {
    double pixspan = pixtrc[j] - (pixblc ? pixblc[j] : 1.0);
d1110 1
a1110 2
  double *pix0 = calloc((3*ncoord+4)*naxis, sizeof(double));
  if (pix0 == 0x0) {
d1114 2
a1115 2
  double *img    = pix0 + naxis*ncoord;
  double *pix1   = img  + naxis*ncoord;
d1117 3
a1119 3
  double *pixend = pixinc + naxis;
  double *sumdis = pixend + naxis;
  double *ssqdis = sumdis + naxis;
d1126 1
a1126 1
  for (int j = 0; j < naxis; j++) {
d1131 2
a1132 3
  double *pix0p = pix0 + naxis;
  double *pix1p = pix1;
  for (int i = 1; i < ncoord; i++) {
d1135 1
a1135 1
    for (int j = 1; j < naxis; j++) {
d1141 1
a1141 1
  for (int j = 0; j < naxis; j++) {
d1145 2
a1146 2
  double sumtot = 0.0;
  double ssqtot = 0.0;
d1150 1
a1150 1
  int carry = 0;
d1152 1
a1152 2
    int status = linp2x(lin, ncoord, naxis, pix0, img);
    if (status) {
d1164 2
a1165 1
    for (int i = 0; i < ncoord; i++) {
d1168 4
a1171 4
      double dssq = 0.0;
      for (int j = 0; j < naxis; j++) {
        double dpix = *(pix1p++) - *(pix0p++);
        double dpx2 = dpix*dpix;
d1181 1
a1181 1
      double totdis = sqrt(dssq);
d1189 1
a1189 1
    for (int j = 1; j < naxis; j++) {
d1196 1
a1196 1
      for (int i = 1; i < ncoord; i++) {
d1207 1
a1207 1
  for (int j = 0; j < naxis; j++) {
d1232 5
d1238 1
a1238 2
  int *mxl = calloc(n, sizeof(int));
  if (mxl == 0x0) {
d1241 1
a1241 3

  int *lxm = calloc(n, sizeof(int));
  if (lxm == 0x0) {
d1246 1
a1246 2
  double *rowmax = calloc(n, sizeof(double));
  if (rowmax == 0x0) {
d1252 1
a1252 2
  double *lu = calloc(n*n, sizeof(double));
  if (lu == 0x0) {
d1261 1
a1261 2
  register int ij = 0;
  for (int i = 0; i < n; i++) {
d1267 2
a1268 2
    for (int j = 0; j < n; j++, ij++) {
      double dtemp = fabs(mat[ij]);
d1286 1
a1286 1
  for (int k = 0; k < n; k++) {
d1288 2
a1289 2
    int pivot = k;
    double colmax = fabs(lu[k*n+k]) / rowmax[k];
d1291 3
a1293 3
    for (int i = k+1; i < n; i++) {
      register int ik = i*n + k;
      double dtemp = fabs(lu[ik]) / rowmax[i];
d1302 2
a1303 4
      register int kj = k*n;
      register int pj = pivot*n;
      for (int j = 0; j < n; j++, pj++, kj++) {
        double dtemp = lu[pj];
d1309 1
a1309 1
      double dtemp = rowmax[pivot];
d1314 1
a1314 1
      int itemp = mxl[pivot];
d1320 2
a1321 2
    for (int i = k+1; i < n; i++) {
      register int ik = i*n + k;
d1329 1
a1329 1
        for (int j = k+1; j < n; j++) {
d1339 1
a1339 1
  for (int i = 0; i < n; i++) {
d1345 2
a1346 3
  ij = 0;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++, ij++) {
d1351 1
a1351 1
  for (int k = 0; k < n; k++) {
d1355 2
a1356 2
    for (int i = lxm[k]+1; i < n; i++) {
      for (int j = lxm[k]; j < i; j++) {
d1362 2
a1363 2
    for (int i = n-1; i >= 0; i--) {
      for (int j = i+1; j < n; j++) {
@


7.6.1.3
log
@Bug fix in linsize() uncovered by gcc 11.1.0.
@
text
@d22 1
a22 1
  $Id: lin.c,v 7.6.1.2 2021/07/01 07:39:45 mcalabre Exp mcalabre $
d463 1
a463 1
  sizes[1] += exsizes[0] + exsizes[1];
d467 1
a467 1
  sizes[1] += exsizes[0] + exsizes[1];
@


7.6.1.4
log
@Replaced a line of code in linwarp() that went missing at 7.6.1.2.
@
text
@d22 1
a22 1
  $Id: lin.c,v 7.6.1.3 2021/07/01 07:50:34 mcalabre Exp mcalabre $
d1055 4
a1058 5

  int status = lincpy(1, lin, &affine) ||
               lindist(1, &affine, 0x0, 0) ||
               lindist(2, &affine, 0x0, 0) ||
               linset(&affine);
d1064 1
a1066 1
    double *pixinc = lin->tmpcrd;
d1087 1
a1087 1
  // Allocate memory in bulk for processing the image row by row.
a1092 1
  // Carve up the allocated memory.
d1095 1
a1095 1
  double *pixinc = pix1 + naxis*ncoord;
d1111 1
d1132 2
a1133 2
    int status;
    if ((status = linp2x(lin, ncoord, naxis, pix0, img))) {
d1144 1
a1144 2
    double *pix0p = pix0;
    double *pix1p = pix1;
@


7.5
log
@WCSLIB 7.5
@
text
@d2 1
a2 1
  WCSLIB 7.5 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: lin.c,v 7.4.1.1 2021/01/31 02:26:24 mcalabre Exp mcalabre $
d25 1
a28 1
#include <math.h>
d441 58
@


7.5.1.1
log
@WCSLIB 7.5 development branch.
@
text
@d22 1
a22 1
  $Id: lin.c,v 7.5 2021/03/20 05:54:58 mcalabre Exp $
@


7.5.1.2
log
@Added new function linsize().
@
text
@d22 1
a22 1
  $Id: lin.c,v 7.5.1.1 2021/03/20 05:56:42 mcalabre Exp mcalabre $
a24 1
#include <math.h>
d28 1
a440 58
}

//----------------------------------------------------------------------------

int linsize(const struct linprm *lin, int sizes[2])

{

  if (lin == 0x0) {
    sizes[0] = sizes[1] = 0;
    return LINERR_SUCCESS;
  }

  // Base size, in bytes.
  sizes[0] = sizeof(struct linprm);

  // Total size of allocated memory, in bytes.
  sizes[1] = 0;

  int exsizes[2];
  int naxis = lin->naxis;

  // linprm::crpix[].
  sizes[1] += naxis * sizeof(double);

  // linprm::pc[].
  sizes[1] += naxis*naxis * sizeof(double);

  // linprm::cdelt[].
  sizes[1] += naxis * sizeof(double);

  // linprm::dispre[].
  dissize(lin->dispre, exsizes);
  sizes[2] += exsizes[0] + exsizes[1];

  // linprm::disseq[].
  dissize(lin->disseq, exsizes);
  sizes[2] += exsizes[0] + exsizes[1];

  // linprm::err[].
  wcserr_size(lin->err, exsizes);
  sizes[1] += exsizes[0] + exsizes[1];

  // The remaining arrays are allocated unconditionally by linset().
  if (lin->flag != LINSET) {
    return LINERR_SUCCESS;
  }

  // linprm::piximg[].
  sizes[1] += naxis*naxis * sizeof(double);

  // linprm::imgpix[].
  sizes[1] += naxis*naxis * sizeof(double);

  // linprm::tmpcrd[].
  sizes[1] += naxis * sizeof(double);

  return LINERR_SUCCESS;
@


7.4
log
@WCSLIB 7.4
@
text
@d2 1
a2 1
  WCSLIB 7.4 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: lin.c,v 7.3.1.5 2021/01/28 12:29:30 mcalabre Exp mcalabre $
@


7.4.1.1
log
@WCSLIB 7.4 development branch.
@
text
@d22 1
a22 1
  $Id: lin.c,v 7.4 2021/01/31 02:24:51 mcalabre Exp $
@


7.3
log
@WCSLIB 7.3
@
text
@d2 2
a3 3

  WCSLIB 7.3 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2020, Mark Calabretta
a19 2
  Direct correspondence concerning WCSLIB to mark@@calabretta.id.au

d22 1
a22 1
  $Id: lin.c,v 7.2.1.1 2020/03/09 07:34:50 mcalabre Exp mcalabre $
d37 1
a37 1
/* Map status return value to message. */
d47 1
a47 1
/* Map error returns for lower-level routines. */
d49 6
a54 6
  LINERR_SUCCESS,		/*  0: DISERR_SUCCESS         */
  LINERR_NULL_POINTER,		/*  1: DISERR_NULL_POINTER    */
  LINERR_MEMORY,		/*  2: DISERR_MEMORY          */
  LINERR_DISTORT_INIT,		/*  3: DISERR_BAD_PARAM       */
  LINERR_DISTORT,		/*  4: DISERR_DISTORT         */
  LINERR_DEDISTORT		/*  5: DISERR_DEDISTORT       */
d57 1
a57 1
/* Convenience macro for invoking wcserr_set(). */
d60 1
a60 1
/*--------------------------------------------------------------------------*/
d68 1
a68 1
/*--------------------------------------------------------------------------*/
d81 1
a81 1
  /* Initialize error message handling. */
d89 1
a89 1
  /* Initialize memory management. */
d112 1
a112 1
  /* Allocate memory for arrays if required. */
d118 1
a118 1
    /* Was sufficient allocated previously? */
d120 1
a120 1
      /* No, free it. */
d126 1
a126 1
        /* In case the caller fiddled with it. */
d142 1
a142 1
        /* In case the caller fiddled with it. */
d159 1
a159 1
        /* In case the caller fiddled with it. */
d176 1
a176 1
  /* Reinitialize disprm structs if we are managing them. */
d186 1
a186 1
  /* Free memory allocated by linset(). */
d206 1
a206 1
  /* CRPIXja defaults to 0.0. */
d211 1
a211 1
  /* PCi_ja defaults to the unit matrix. */
d224 1
a224 1
  /* CDELTia defaults to 1.0. */
d233 1
a233 1
/*--------------------------------------------------------------------------*/
d241 1
a241 1
/*--------------------------------------------------------------------------*/
d288 1
a288 1
/*--------------------------------------------------------------------------*/
d384 1
a384 1
/*--------------------------------------------------------------------------*/
d392 1
a392 1
    /* Optionally allocated by lininit() for given parameters. */
d415 1
a415 1
    /* Allocated unconditionally by linset(). */
d443 1
a443 1
/*--------------------------------------------------------------------------*/
d458 1
a458 1
  /* Parameters supplied. */
d492 1
a492 1
  /* Derived values. */
d524 1
a524 1
  /* Error handling. */
d530 1
a530 1
  /* Work arrays. */
d533 1
a533 1
  /* Memory management. */
d552 1
a552 1
  /* Distortion parameters (from above). */
d568 1
a568 1
/*--------------------------------------------------------------------------*/
d583 1
a583 1
/*--------------------------------------------------------------------------*/
d599 1
a599 1
  /* Check for a unit matrix. */
d621 1
a621 1
      /* Free memory that may have been allocated previously. */
d630 1
a630 1
    /* Check cdelt. */
d640 1
a640 1
        /* Free memory that may have been allocated previously. */
d645 1
a645 1
      /* Allocate memory for internal arrays. */
d658 1
a658 1
    /* Compute the pixel-to-image transformation matrix. */
d662 3
a664 3
      for (j = 0; j < naxis; j++) {
        if (lin->disseq == 0x0) {
          /* No sequent distortions, incorporate cdelt into piximg. */
d666 3
a668 1
        } else {
d674 1
a674 1
    /* Compute the image-to-pixel transformation matrix. */
d681 1
a681 1
  /* Set up the distortion functions. */
d702 1
a702 1
  /* Create work arrays. */
d715 1
a715 1
/*--------------------------------------------------------------------------*/
d734 1
a734 1
  /* Initialize. */
d745 1
a745 1
  /* Convert pixel coordinates to intermediate world coordinates. */
d750 1
a750 1
    /* Handle the simplest and most common case with maximum efficiency. */
d762 1
a762 1
    /* No distortions. */
d769 1
a769 1
        /* cdelt will have been incorporated into piximg. */
d772 1
a772 1
        /* Column-wise multiplication allows this to be cached. */
d784 1
a784 1
    /* Distortions are present. */
d821 1
a821 1
        /* With sequent distortions, cdelt is not incorporated into piximg. */
d827 1
a827 1
        /* ...nor if the matrix is unity. */
d841 1
a841 1
/*--------------------------------------------------------------------------*/
d859 1
a859 1
  /* Initialize. */
d870 1
a870 1
  /* Convert intermediate world coordinates to pixel coordinates. */
d875 1
a875 1
    /* Handle the simplest and most common case with maximum efficiency. */
d887 1
a887 1
    /* No distortions. */
d890 1
a890 1
      /* cdelt will have been incorporated into imgpix. */
d908 1
a908 1
    /* Distortions are present. */
d914 1
a914 1
        /* With sequent distortions, cdelt is not incorporated into imgpix. */
d926 1
a926 1
        /* ...nor if the matrix is unity. */
d932 1
a932 1
        /* cdelt will have been incorporated into imgpix. */
d967 1
a967 1
/*--------------------------------------------------------------------------*/
d992 1
a992 1
  /* Initialize. */
d1008 1
a1008 1
  /* Quick return if no distortions. */
d1011 1
a1011 1
  /* It's easier if there are no sequent distortions! */
d1018 1
a1018 1
  /* Make a reference copy of lin without distortions. */
d1027 1
a1027 1
  /* Work out increments on each axis. */
d1046 1
a1046 1
      /* Number of samples on axis 1. */
d1051 1
a1051 1
  /* Get memory for processing the image row by row. */
d1064 1
a1064 1
  /* Copy tmpcrd since linp2x() will overwrite it. */
d1067 1
a1067 1
  /* Set up the array of pixel coordinates. */
d1082 1
a1082 1
  /* Initialize accumulators. */
d1091 1
a1091 1
  /* Loop over N dimensions. */
d1095 1
a1095 1
      /* (Preserve the error message set by linp2x().) */
d1100 1
a1100 1
      /* (Preserve the error message set by linx2p().) */
d1104 1
a1104 1
    /* Accumulate statistics. */
d1130 1
a1130 1
    /* Next array of pixel coordinates. */
d1148 1
a1148 1
  /* Compute the means and RMSs. */
d1169 1
a1169 1
/*--------------------------------------------------------------------------*/
d1179 1
a1179 1
  /* Allocate memory for internal arrays. */
d1202 1
a1202 1
  /* Initialize arrays. */
d1204 1
a1204 1
    /* Vector that records row interchanges. */
d1216 1
a1216 1
    /* A row of zeroes indicates a singular matrix. */
d1227 1
a1227 1
  /* Form the LU triangular factorization using scaled partial pivoting. */
d1229 1
a1229 1
    /* Decide whether to pivot. */
d1243 1
a1243 1
      /* We must pivot, interchange the rows of the design matrix. */
d1250 1
a1250 1
      /* Amend the vector of row maxima. */
d1255 1
a1255 1
      /* Record the interchange for later use. */
d1261 1
a1261 1
    /* Gaussian elimination. */
d1265 1
a1265 1
      /* Nothing to do if lu[ik] is zero. */
d1267 1
a1267 1
        /* Save the scaling factor. */
d1270 1
a1270 1
        /* Subtract rows. */
d1279 2
a1280 2
  /* mxl[i] records which row of mat corresponds to row i of lu.  */
  /* lxm[i] records which row of lu  corresponds to row i of mat. */
d1286 1
a1286 1
  /* Determine the inverse matrix. */
d1296 1
a1296 1
    /* Forward substitution. */
d1303 1
a1303 1
    /* Backward substitution. */
@


7.3.1.1
log
@WCSLIB 7.3 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 7.3 2020/06/03 03:37:02 mcalabre Exp $
@


7.3.1.2
log
@Switched to C99 style commenting (i.e. using //) within the code.
@
text
@d2 1
d25 1
a25 1
  $Id: lin.c,v 7.3.1.1 2020/06/03 03:38:10 mcalabre Exp mcalabre $
d40 1
a40 1
// Map status return value to message.
d50 1
a50 1
// Map error returns for lower-level routines.
d52 6
a57 6
  LINERR_SUCCESS,		//  0: DISERR_SUCCESS
  LINERR_NULL_POINTER,		//  1: DISERR_NULL_POINTER
  LINERR_MEMORY,		//  2: DISERR_MEMORY
  LINERR_DISTORT_INIT,		//  3: DISERR_BAD_PARAM
  LINERR_DISTORT,		//  4: DISERR_DISTORT
  LINERR_DEDISTORT		//  5: DISERR_DEDISTORT
d60 1
a60 1
// Convenience macro for invoking wcserr_set().
d63 1
a63 1
//----------------------------------------------------------------------------
d71 1
a71 1
//----------------------------------------------------------------------------
d84 1
a84 1
  // Initialize error message handling.
d92 1
a92 1
  // Initialize memory management.
d115 1
a115 1
  // Allocate memory for arrays if required.
d121 1
a121 1
    // Was sufficient allocated previously?
d123 1
a123 1
      // No, free it.
d129 1
a129 1
        // In case the caller fiddled with it.
d145 1
a145 1
        // In case the caller fiddled with it.
d162 1
a162 1
        // In case the caller fiddled with it.
d179 1
a179 1
  // Reinitialize disprm structs if we are managing them.
d189 1
a189 1
  // Free memory allocated by linset().
d209 1
a209 1
  // CRPIXja defaults to 0.0.
d214 1
a214 1
  // PCi_ja defaults to the unit matrix.
d227 1
a227 1
  // CDELTia defaults to 1.0.
d236 1
a236 1
//----------------------------------------------------------------------------
d244 1
a244 1
//----------------------------------------------------------------------------
d291 1
a291 1
//----------------------------------------------------------------------------
d387 1
a387 1
//----------------------------------------------------------------------------
d395 1
a395 1
    // Optionally allocated by lininit() for given parameters.
d418 1
a418 1
    // Allocated unconditionally by linset().
d446 1
a446 1
//----------------------------------------------------------------------------
d461 1
a461 1
  // Parameters supplied.
d495 1
a495 1
  // Derived values.
d527 1
a527 1
  // Error handling.
d533 1
a533 1
  // Work arrays.
d536 1
a536 1
  // Memory management.
d555 1
a555 1
  // Distortion parameters (from above).
d571 1
a571 1
//----------------------------------------------------------------------------
d586 1
a586 1
//----------------------------------------------------------------------------
d602 1
a602 1
  // Check for a unit matrix.
d624 1
a624 1
      // Free memory that may have been allocated previously.
d633 1
a633 1
    // Check cdelt.
d643 1
a643 1
        // Free memory that may have been allocated previously.
d648 1
a648 1
      // Allocate memory for internal arrays.
d661 1
a661 1
    // Compute the pixel-to-image transformation matrix.
d667 1
a667 1
          // No sequent distortions, incorporate cdelt into piximg.
d675 1
a675 1
    // Compute the image-to-pixel transformation matrix.
d682 1
a682 1
  // Set up the distortion functions.
d703 1
a703 1
  // Create work arrays.
d716 1
a716 1
//----------------------------------------------------------------------------
d735 1
a735 1
  // Initialize.
d746 1
a746 1
  // Convert pixel coordinates to intermediate world coordinates.
d751 1
a751 1
    // Handle the simplest and most common case with maximum efficiency.
d763 1
a763 1
    // No distortions.
d770 1
a770 1
        // cdelt will have been incorporated into piximg.
d773 1
a773 1
        // Column-wise multiplication allows this to be cached.
d785 1
a785 1
    // Distortions are present.
d822 1
a822 1
        // With sequent distortions, cdelt is not incorporated into piximg.
d828 1
a828 1
        // ...nor if the matrix is unity.
d842 1
a842 1
//----------------------------------------------------------------------------
d860 1
a860 1
  // Initialize.
d871 1
a871 1
  // Convert intermediate world coordinates to pixel coordinates.
d876 1
a876 1
    // Handle the simplest and most common case with maximum efficiency.
d888 1
a888 1
    // No distortions.
d891 1
a891 1
      // cdelt will have been incorporated into imgpix.
d909 1
a909 1
    // Distortions are present.
d915 1
a915 1
        // With sequent distortions, cdelt is not incorporated into imgpix.
d927 1
a927 1
        // ...nor if the matrix is unity.
d933 1
a933 1
        // cdelt will have been incorporated into imgpix.
d968 1
a968 1
//----------------------------------------------------------------------------
d993 1
a993 1
  // Initialize.
d1009 1
a1009 1
  // Quick return if no distortions.
d1012 1
a1012 1
  // It's easier if there are no sequent distortions!
d1019 1
a1019 1
  // Make a reference copy of lin without distortions.
d1028 1
a1028 1
  // Work out increments on each axis.
d1047 1
a1047 1
      // Number of samples on axis 1.
d1052 1
a1052 1
  // Get memory for processing the image row by row.
d1065 1
a1065 1
  // Copy tmpcrd since linp2x() will overwrite it.
d1068 1
a1068 1
  // Set up the array of pixel coordinates.
d1083 1
a1083 1
  // Initialize accumulators.
d1092 1
a1092 1
  // Loop over N dimensions.
d1096 1
a1096 1
      // (Preserve the error message set by linp2x().)
d1101 1
a1101 1
      // (Preserve the error message set by linx2p().)
d1105 1
a1105 1
    // Accumulate statistics.
d1131 1
a1131 1
    // Next array of pixel coordinates.
d1149 1
a1149 1
  // Compute the means and RMSs.
d1170 1
a1170 1
//----------------------------------------------------------------------------
d1180 1
a1180 1
  // Allocate memory for internal arrays.
d1203 1
a1203 1
  // Initialize arrays.
d1205 1
a1205 1
    // Vector that records row interchanges.
d1217 1
a1217 1
    // A row of zeroes indicates a singular matrix.
d1228 1
a1228 1
  // Form the LU triangular factorization using scaled partial pivoting.
d1230 1
a1230 1
    // Decide whether to pivot.
d1244 1
a1244 1
      // We must pivot, interchange the rows of the design matrix.
d1251 1
a1251 1
      // Amend the vector of row maxima.
d1256 1
a1256 1
      // Record the interchange for later use.
d1262 1
a1262 1
    // Gaussian elimination.
d1266 1
a1266 1
      // Nothing to do if lu[ik] is zero.
d1268 1
a1268 1
        // Save the scaling factor.
d1271 1
a1271 1
        // Subtract rows.
d1280 2
a1281 2
  // mxl[i] records which row of mat corresponds to row i of lu.
  // lxm[i] records which row of lu  corresponds to row i of mat.
d1287 1
a1287 1
  // Determine the inverse matrix.
d1297 1
a1297 1
    // Forward substitution.
d1304 1
a1304 1
    // Backward substitution.
@


7.3.1.3
log
@Minor efficiency tweak in linset().
@
text
@d24 1
a24 1
  $Id: lin.c,v 7.3.1.2 2020/08/17 11:19:09 mcalabre Exp mcalabre $
d664 3
a666 3
      if (lin->disseq == 0x0) {
        // No sequent distortions.  Incorporate cdelt into piximg.
        for (j = 0; j < naxis; j++) {
d668 1
a668 3
        }
      } else {
        for (j = 0; j < naxis; j++) {
d821 1
a821 1
        // With sequent distortions, cdelt is not incorporated into piximg...
d914 1
a914 1
        // With sequent distortions, cdelt is not incorporated into imgpix...
@


7.3.1.4
log
@Updated date in copyright notice.
@
text
@d3 1
a3 1
  Copyright (C) 1995-2021, Mark Calabretta
d24 1
a24 1
  $Id: lin.c,v 7.3.1.3 2020/09/21 08:24:44 mcalabre Exp mcalabre $
@


7.3.1.5
log
@Removed my email address from the copyright notice.
@
text
@d20 2
d24 1
a24 1
  $Id: lin.c,v 7.3.1.4 2021/01/19 14:09:10 mcalabre Exp mcalabre $
@


7.2
log
@WCSLIB 7.2
@
text
@d3 1
a3 1
  WCSLIB 7.2 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 7.1.1.1 2019/12/31 13:28:19 mcalabre Exp mcalabre $
@


7.2.1.1
log
@WCSLIB 7.2 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 7.2 2020/03/09 07:31:23 mcalabre Exp $
@


7.1
log
@WCSLIB 7.1
@
text
@d3 1
a3 1
  WCSLIB 7.1 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 6.4.1.2 2019/12/31 03:28:03 mcalabre Exp mcalabre $
@


7.1.1.1
log
@WCSLIB 7.1 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 7.1 2019/12/31 13:25:19 mcalabre Exp $
@


6.4
log
@WCSLIB 6.4
@
text
@d3 2
a4 2
  WCSLIB 6.4 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2019, Mark Calabretta
d25 1
a25 1
  $Id: lin.c,v 6.3.1.1 2019/07/12 07:34:37 mcalabre Exp mcalabre $
@


6.4.1.1
log
@WCSLIB 6.4 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 6.4 2019/08/15 09:30:18 mcalabre Exp $
@


6.4.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2020, Mark Calabretta
d25 1
a25 1
  $Id: lin.c,v 6.4.1.1 2019/08/15 09:31:29 mcalabre Exp mcalabre $
@


6.3
log
@WCSLIB 6.3
@
text
@d3 1
a3 1
  WCSLIB 6.3 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 6.2.1.4 2019/07/09 08:47:43 mcalabre Exp mcalabre $
@


6.3.1.1
log
@WCSLIB 6.3 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 6.3 2019/07/12 07:33:39 mcalabre Exp $
@


6.2
log
@WCSLIB 6.2
@
text
@d3 2
a4 2
  WCSLIB 6.2 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2018, Mark Calabretta
d25 1
a25 1
  $Id: lin.c,v 6.1.1.1 2018/10/19 08:36:15 mcalabre Exp mcalabre $
d85 3
d89 1
a89 4
  if (lin->flag != -1) {
    if (lin->err) free(lin->err);
  }
  lin->err = 0x0;
a421 2

    if (lin->err) free(lin->err);
d439 1
a439 1
  lin->err  = 0x0;
@


6.2.1.1
log
@WCSLIB 6.2 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 6.2 2018/10/20 10:03:13 mcalabre Exp $
@


6.2.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2019, Mark Calabretta
d25 1
a25 1
  $Id: lin.c,v 6.2.1.1 2018/10/20 10:04:15 mcalabre Exp mcalabre $
@


6.2.1.3
log
@In lininit() and linfree(), use wcserr_clear() to free the wcserr struct,
including any memory that may have been allocated to store a message.
@
text
@d25 1
a25 1
  $Id: lin.c,v 6.2.1.2 2019/05/10 01:56:50 mcalabre Exp mcalabre $
d87 1
a87 1
    wcserr_clear(err);
d423 1
a423 1
    wcserr_clear(&(lin->err));
@


6.2.1.4
log
@Refinements for error message handling in lininit() and linfree().
@
text
@d25 1
a25 1
  $Id: lin.c,v 6.2.1.3 2019/07/08 13:07:51 mcalabre Exp mcalabre $
d85 3
a87 2
  if (lin->flag == -1) {
    lin->err = 0x0;
d89 1
a89 2
  err = &(lin->err);
  wcserr_clear(err);
d422 2
d441 1
a441 1
  wcserr_clear(&(lin->err));
@


6.1
log
@WCSLIB 6.1
@
text
@d3 1
a3 1
  WCSLIB 6.1 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 5.20.1.1 2018/10/05 05:33:33 mcalabre Exp mcalabre $
@


6.1.1.1
log
@WCSLIB 6.1 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 6.1 2018/10/19 08:35:17 mcalabre Exp $
@


5.20
log
@WCSLIB 5.20
@
text
@d3 1
a3 1
  WCSLIB 5.20 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 5.19.1.1 2018/07/26 15:41:40 mcalabre Exp mcalabre $
@


5.20.1.1
log
@WCSLIB 5.20 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.20 2018/10/05 05:32:41 mcalabre Exp $
@


5.19
log
@WCSLIB 5.19
@
text
@d3 1
a3 1
  WCSLIB 5.19 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 5.18.1.2 2018/07/25 06:21:08 mcalabre Exp mcalabre $
@


5.19.1.1
log
@WCSLIB 5.19 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.19 2018/07/26 15:37:04 mcalabre Exp $
@


5.18
log
@WCSLIB 5.18
@
text
@d3 1
a3 1
  WCSLIB 5.18 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 5.17.1.5 2018/01/10 08:25:34 mcalabre Exp mcalabre $
d1032 1
@


5.18.1.1
log
@WCSLIB 5.18 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.18 2018/01/10 08:32:14 mcalabre Exp $
@


5.18.1.2
log
@In linwarp(), avert a nuisance compiler warning about possible use of an
uninitialized variable (gcc -Wmaybe-uninitialized).
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.18.1.1 2018/01/10 08:33:04 mcalabre Exp mcalabre $
a1031 1
  ncoord = 0;
@


5.17
log
@WCSLIB 5.17
@
text
@d3 2
a4 2
  WCSLIB 5.17 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2017, Mark Calabretta
d25 1
a25 1
  $Id: lin.c,v 5.16.1.1 2017/01/15 04:28:59 mcalabre Exp mcalabre $
d68 9
a76 1
  static const char *function = "linini";
d181 1
a181 1
    disini(1, naxis, lin->dispre);
d185 1
a185 1
    disini(1, naxis, lin->disseq);
d241 9
a249 1
  static const char *function = "lindis";
d258 4
a261 1
    if (lin->m_dispre) free(lin->m_dispre);
d268 4
a271 1
    if (lin->m_disseq) free(lin->m_disseq);
d283 1
a283 1
    if ((status = disini(1, lin->naxis, dis))) {
d313 1
a313 1
  if ((status = linini(alloc, naxis, lindst))) {
d368 14
a381 5
  if (status && (lindst->m_dispre || lindst->m_disseq)) {
    if (lindst->dispre) free(lindst->dispre);
    if (lindst->disseq) free(lindst->disseq);
    lindst->dispre = 0x0;
    lindst->disseq = 0x0;
d395 1
a395 1
    /* Optionally allocated by linini() for given parameters. */
d1024 2
a1025 2
                 lindis(1, &affine, 0x0) ||
                 lindis(2, &affine, 0x0) ||
d1165 1
@


5.17.1.1
log
@WCSLIB 5.17 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.17 2017/09/18 08:44:23 mcalabre Exp $
@


5.17.1.2
log
@In lindis(), call disfree() to free allocated memory in the disprm structs
before freeing the structs themselves.  Likewise in the cleanup section of
lincpy(), with additional corrections.
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.17.1.1 2017/09/18 08:45:59 mcalabre Exp mcalabre $
d242 1
a242 4
    if (lin->m_dispre) {
      disfree(lin->m_dispre);
      free(lin->m_dispre);
    }
d249 1
a249 4
    if (lin->m_disseq) {
      disfree(lin->m_disseq);
      free(lin->m_disseq);
    }
d346 5
a350 14
  if (status) {
    if (lindst->m_dispre) {
      disfree(lindst->m_dispre);
      free(lindst->m_dispre);
      lindst->m_dispre = 0x0;
      lindst->dispre = 0x0;
    }

    if (lindst->m_disseq) {
      disfree(lindst->m_disseq);
      free(lindst->m_disseq);
      lindst->m_disseq = 0x0;
      lindst->disseq = 0x0;
    }
a1133 1
  linfree(&affine);
@


5.17.1.3
log
@Added new functions lininit() and lindist(), with linini() and lindis() now
thin wrappers over them.
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.17.1.2 2017/12/05 01:41:54 mcalabre Exp mcalabre $
d68 1
a68 9
  return lininit(alloc, naxis, lin, -1);
}

/*--------------------------------------------------------------------------*/

int lininit(int alloc, int naxis, struct linprm *lin, int ndpmax)

{
  static const char *function = "lininit";
d173 1
a173 1
    disinit(1, naxis, lin->dispre, ndpmax);
d177 1
a177 1
    disinit(1, naxis, lin->disseq, ndpmax);
d233 1
a233 9
  return lindist(sequence, lin, dis, -1);
}

/*--------------------------------------------------------------------------*/

int lindist(int sequence, struct linprm *lin, struct disprm *dis, int ndpmax)

{
  static const char *function = "lindist";
d267 1
a267 1
    if ((status = disinit(1, lin->naxis, dis, ndpmax))) {
d379 1
a379 1
    /* Optionally allocated by lininit() for given parameters. */
@


5.17.1.4
log
@In lincpy(), replaced a call to linini() with lininit(), and in linwarp(),
replaced two calls to lindis() with lindist().
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.17.1.3 2017/12/05 07:39:40 mcalabre Exp mcalabre $
d313 1
a313 1
  if ((status = lininit(alloc, naxis, lindst, 0))) {
d1024 2
a1025 2
                 lindist(1, &affine, 0x0, 0) ||
                 lindist(2, &affine, 0x0, 0) ||
@


5.17.1.5
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2018, Mark Calabretta
d25 1
a25 1
  $Id: lin.c,v 5.17.1.4 2017/12/05 21:13:56 mcalabre Exp mcalabre $
@


5.16
log
@WCSLIB 5.16
@
text
@d3 1
a3 1
  WCSLIB 5.16 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 5.15.1.2 2017/01/15 04:13:33 mcalabre Exp mcalabre $
@


5.16.1.1
log
@WCSLIB 5.16 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.16 2017/01/15 04:25:01 mcalabre Exp $
@


5.15
log
@WCSLIB 5.15
@
text
@d3 2
a4 2
  WCSLIB 5.15 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2016, Mark Calabretta
d25 1
a25 1
  $Id: lin.c,v 5.14.1.1 2016/02/07 10:52:44 mcalabre Exp mcalabre $
@


5.15.1.1
log
@WCSLIB 5.15 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.15 2016/04/05 12:55:10 mcalabre Exp $
@


5.15.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2017, Mark Calabretta
d25 1
a25 1
  $Id: lin.c,v 5.15.1.1 2016/04/05 12:58:35 mcalabre Exp mcalabre $
@


5.14
log
@WCSLIB 5.14
@
text
@d3 1
a3 1
  WCSLIB 5.14 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 5.13.1.1 2016/01/26 08:54:32 mcalabre Exp mcalabre $
@


5.14.1.1
log
@WCSLIB 5.14 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.14 2016/02/07 10:49:31 mcalabre Exp $
@


5.13
log
@WCSLIB 5.13
@
text
@d3 1
a3 1
  WCSLIB 5.13 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 5.12.1.2 2016/01/25 05:17:04 mcalabre Exp mcalabre $
@


5.13.1.1
log
@WCSLIB 5.13 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.13 2016/01/26 08:51:13 mcalabre Exp $
@


5.12
log
@WCSLIB 5.12
@
text
@d3 2
a4 2
  WCSLIB 5.12 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2015, Mark Calabretta
d25 1
a25 1
  $Id: lin.c,v 5.11.1.1 2015/10/18 09:16:27 mcalabre Exp mcalabre $
@


5.12.1.1
log
@WCSLIB 5.12 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.12 2015/11/15 02:13:00 mcalabre Exp $
@


5.12.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2016, Mark Calabretta
d25 1
a25 1
  $Id: lin.c,v 5.12.1.1 2015/11/15 02:16:14 mcalabre Exp mcalabre $
@


5.11
log
@WCSLIB 5.11
@
text
@d3 1
a3 1
  WCSLIB 5.11 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 5.10.1.1 2015/10/09 08:22:35 mcalabre Exp mcalabre $
@


5.11.1.1
log
@WCSLIB 5.11 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.11 2015/10/18 09:13:05 mcalabre Exp $
@


5.10
log
@WCSLIB 5.10
@
text
@d3 1
a3 1
  WCSLIB 5.10 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 5.9.1.1 2015/07/21 09:28:07 mcalabre Exp mcalabre $
@


5.10.1.1
log
@WCSLIB 5.10 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.10 2015/10/09 08:19:15 mcalabre Exp $
@


5.9
log
@WCSLIB 5.9
@
text
@d3 1
a3 1
  WCSLIB 5.9 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 5.8.1.1 2015/07/08 11:07:18 mcalabre Exp mcalabre $
@


5.9.1.1
log
@WCSLIB 5.9 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.9 2015/07/21 09:20:01 mcalabre Exp $
@


5.8
log
@WCSLIB 5.8
@
text
@d3 1
a3 1
  WCSLIB 5.8 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 5.7.1.1 2015/06/29 02:47:24 mcalabre Exp mcalabre $
@


5.8.1.1
log
@WCSLIB 5.8 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.8 2015/07/08 11:03:59 mcalabre Exp $
@


5.7
log
@WCSLIB 5.7
@
text
@d3 1
a3 1
  WCSLIB 5.7 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 5.6.1.1 2015/06/14 07:14:44 mcalabre Exp mcalabre $
@


5.7.1.1
log
@WCSLIB 5.7 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.7 2015/06/29 02:44:16 mcalabre Exp $
@


5.6
log
@WCSLIB 5.6
@
text
@d3 1
a3 1
  WCSLIB 5.6 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 5.5.1.1 2015/05/05 13:21:00 mcalabre Exp mcalabre $
@


5.6.1.1
log
@WCSLIB 5.6 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.6 2015/06/14 07:11:24 mcalabre Exp $
@


5.5
log
@WCSLIB 5.5
@
text
@d3 1
a3 1
  WCSLIB 5.5 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 5.4.1.1 2015/04/21 14:44:28 mcalabre Exp mcalabre $
@


5.5.1.1
log
@WCSLIB 5.5 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.5 2015/05/05 13:16:31 mcalabre Exp $
@


5.4
log
@WCSLIB 5.4
@
text
@d3 1
a3 1
  WCSLIB 5.4 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 5.3.1.1 2015/04/21 02:54:02 mcalabre Exp mcalabre $
@


5.4.1.1
log
@WCSLIB 5.4 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.4 2015/04/21 14:41:05 mcalabre Exp $
@


5.3
log
@WCSLIB 5.3
@
text
@d3 1
a3 1
  WCSLIB 5.3 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 5.2.1.2 2015/04/21 01:38:48 mcalabre Exp mcalabre $
@


5.3.1.1
log
@WCSLIB 5.3 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.3 2015/04/21 02:50:51 mcalabre Exp $
@


5.2
log
@WCSLIB 5.2
@
text
@d3 1
a3 1
  WCSLIB 5.2 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 5.1.1.5 2015/04/15 09:16:34 mcalabre Exp mcalabre $
d1066 1
a1066 1
      wcserr_set(LIN_ERRMSG(status));
d1071 1
a1071 1
      wcserr_set(LIN_ERRMSG(status));
@


5.2.1.1
log
@WCSLIB 5.2 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.2 2015/04/15 12:35:07 mcalabre Exp $
@


5.2.1.2
log
@In linwarp(), preserve error messages set by linp2x() and linx2p().
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.2.1.1 2015/04/15 12:39:14 mcalabre Exp mcalabre $
d1066 1
a1066 1
      /* (Preserve the error message set by linp2x().) */
d1071 1
a1071 1
      /* (Preserve the error message set by linx2p().) */
@


5.1
log
@WCSLIB 5.1
@
text
@d3 1
a3 1
  WCSLIB 5.1 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 5.0.1.2 2015/04/07 08:46:25 mcalabre Exp mcalabre $
a106 8
  /* Create work arrays. */
  if (lin->tmpcrd) free(lin->tmpcrd);
  if ((lin->tmpcrd = calloc(naxis, sizeof(double))) == 0x0) {
    linfree(lin);
    return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
  }


d185 1
d194 2
d364 1
a364 1
    /* Free memory allocated by linini(). */
a371 2
      if (lin->tmpcrd)   free(lin->tmpcrd);

d386 7
a394 1
  lin->tmpcrd   = 0x0;
d404 3
d408 1
a408 9
  /* Free memory allocated by linset(). */
  if (lin->flag == LINSET) {
    if (lin->piximg) free(lin->piximg);
    if (lin->imgpix) free(lin->imgpix);
  }

  lin->piximg  = 0x0;
  lin->imgpix  = 0x0;
  lin->i_naxis = 0;
d410 1
a410 4
  if (lin->err) {
    free(lin->err);
    lin->err = 0x0;
  }
d564 1
a564 1
  int i, j, n, status;
d571 1
a571 1
  n = lin->naxis;
d576 2
a577 2
  for (i = 0; i < n; i++) {
    for (j = 0; j < n; j++) {
d605 1
a605 1
    for (i = 0; i < n; i++) {
d612 1
a612 1
    if (lin->flag != LINSET || lin->i_naxis < n) {
d620 1
a620 1
      if ((lin->piximg = calloc(n*n, sizeof(double))) == 0x0) {
d624 1
a624 1
      if ((lin->imgpix = calloc(n*n, sizeof(double))) == 0x0) {
d629 1
a629 1
      lin->i_naxis = n;
d635 2
a636 2
    for (i = 0; i < n; i++) {
      for (j = 0; j < n; j++) {
d647 1
a647 1
    if ((status = matinv(n, lin->piximg, lin->imgpix))) {
d674 8
d1094 1
a1097 1
      totdis = sqrt(dssq);
d1280 1
a1280 1
   }
d1282 4
a1285 4
   free(mxl);
   free(lxm);
   free(rowmax);
   free(lu);
d1287 1
a1287 1
   return 0;
@


5.1.1.1
log
@WCSLIB 5.1 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.1 2015/04/07 10:56:36 mcalabre Exp $
@


5.1.1.2
log
@Bug fix in linwarp().
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.1.1.1 2015/04/07 11:01:10 mcalabre Exp mcalabre $
a1094 1
      totdis = sqrt(dssq);
d1098 1
@


5.1.1.3
log
@Fixed indentation in matinv().
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.1.1.2 2015/04/07 23:28:05 mcalabre Exp mcalabre $
d1281 1
a1281 1
  }
d1283 4
a1286 4
  free(mxl);
  free(lxm);
  free(rowmax);
  free(lu);
d1288 1
a1288 1
  return 0;
@


5.1.1.4
log
@In linfree(), don't try to free piximg, imgpix, or err if flag == -1.
Free tmpcrd regardless of the value of m_flag.
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.1.1.3 2015/04/07 23:43:33 mcalabre Exp mcalabre $
d107 8
a201 9

  /* Create work arrays. */
  if (lin->tmpcrd) free(lin->tmpcrd);
  if ((lin->tmpcrd = calloc(naxis, sizeof(double))) == 0x0) {
    linfree(lin);
    return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
  }


d369 1
a369 1
    /* Optionally allocated by linini() for given parameters. */
d377 2
a392 7

    /* Allocated unconditionally by linini() or linset(). */
    if (lin->piximg) free(lin->piximg);
    if (lin->imgpix) free(lin->imgpix);
    if (lin->tmpcrd) free(lin->tmpcrd);

    if (lin->err) free(lin->err);
d395 1
a404 3
  lin->piximg   = 0x0;
  lin->imgpix   = 0x0;
  lin->i_naxis  = 0;
d406 9
a414 1
  lin->tmpcrd   = 0x0;
d416 4
a419 1
  lin->err  = 0x0;
@


5.1.1.5
log
@Moved the allocation of memory for linprm::tmpcrd from linini() to linset().
Mainly required by the Fortran wrappers - any wcsprm struct created by
WCSVCOPY as a shallow copy of another wcsprm struct won't be able to invoke
wcsini() as it resets all "given" members to default values.
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.1.1.4 2015/04/13 08:24:25 mcalabre Exp mcalabre $
a184 1
    if (lin->tmpcrd) free(lin->tmpcrd);
d193 8
a200 1
  lin->tmpcrd  = 0x0;
d393 1
a393 1
    /* Allocated unconditionally by linset(). */
d570 1
a570 1
  int i, j, naxis, status;
d577 1
a577 1
  naxis = lin->naxis;
d582 2
a583 2
  for (i = 0; i < naxis; i++) {
    for (j = 0; j < naxis; j++) {
d611 1
a611 1
    for (i = 0; i < naxis; i++) {
d618 1
a618 1
    if (lin->flag != LINSET || lin->i_naxis < naxis) {
d626 1
a626 1
      if ((lin->piximg = calloc(naxis*naxis, sizeof(double))) == 0x0) {
d630 1
a630 1
      if ((lin->imgpix = calloc(naxis*naxis, sizeof(double))) == 0x0) {
d635 1
a635 1
      lin->i_naxis = naxis;
d641 2
a642 2
    for (i = 0; i < naxis; i++) {
      for (j = 0; j < naxis; j++) {
d653 1
a653 1
    if ((status = matinv(naxis, lin->piximg, lin->imgpix))) {
a677 8


  /* Create work arrays. */
  if (lin->tmpcrd) free(lin->tmpcrd);
  if ((lin->tmpcrd = calloc(naxis, sizeof(double))) == 0x0) {
    linfree(lin);
    return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
  }
@


5.0
log
@WCSLIB 5.0
@
text
@d3 1
a3 1
  WCSLIB 5.0 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 4.25.1.4 2015/04/03 04:09:46 mcalabre Exp mcalabre $
d613 7
d659 1
d662 5
a666 8
    /* Set up the distortion functions. */
    lin->affine = 1;
    if (lin->dispre) {
      if ((status = disset(lin->dispre))) {
        return wcserr_set(LIN_ERRMSG(lin_diserr[status]));
      }

      lin->affine = 0;
d669 2
a670 4
    if (lin->disseq) {
      if ((status = disset(lin->disseq))) {
        return wcserr_set(LIN_ERRMSG(lin_diserr[status]));
      }
d672 3
a674 1
      lin->affine = 0;
d676 2
d772 1
a772 1
          img[i] = lin->cdelt[i] * (tmp[i] - lin->crpix[i]);
d798 6
d898 6
d905 1
d909 4
a912 1
      imgpix = lin->imgpix;
d914 7
a920 4
      for (j = 0; j < n; j++) {
        pix[j] = lin->crpix[j];
        for (i = 0; i < n; i++) {
          pix[j] += *(imgpix++) * tmp[i];
d938 200
@


5.0.1.1
log
@WCSLIB 5.0 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.0 2015/04/05 12:24:59 mcalabre Exp $
@


5.0.1.2
log
@Distortions-related bug fixes in linset(), linp2x(), and linx2p().
New function linwarp() computes various measures of the distortion over the
specified range of pixel coordinates.
@
text
@d25 1
a25 1
  $Id: lin.c,v 5.0.1.1 2015/04/05 12:28:00 mcalabre Exp mcalabre $
a612 7
    /* Check cdelt. */
    for (i = 0; i < n; i++) {
      if (lin->cdelt[i] == 0.0) {
        return wcserr_set(LIN_ERRMSG(LINERR_SINGULAR_MTX));
      }
    }

a651 1
  }
d654 8
a661 5
  /* Set up the distortion functions. */
  lin->affine = 1;
  if (lin->dispre) {
    if ((status = disset(lin->dispre))) {
      return wcserr_set(LIN_ERRMSG(lin_diserr[status]));
d664 4
a667 2
    lin->affine = 0;
  }
d669 1
a669 3
  if (lin->disseq) {
    if ((status = disset(lin->disseq))) {
      return wcserr_set(LIN_ERRMSG(lin_diserr[status]));
a670 2

    lin->affine = 0;
d765 1
a765 1
          img[i] = tmp[i] - lin->crpix[i];
a790 6

      } else if (lin->unity) {
        /* ...nor if the matrix is unity. */
        for (i = 0; i < n; i++) {
          img[i] *= lin->cdelt[i];
        }
a884 6
      } else if (lin->unity) {
        /* ...nor if the matrix is unity. */
        for (i = 0; i < n; i++) {
          tmp[i] = img[i] / lin->cdelt[i];
        }

a885 1
        /* cdelt will have been incorporated into imgpix. */
d889 1
a889 4
      if (lin->unity) {
        for (j = 0; j < n; j++) {
          pix[j] = tmp[j] + lin->crpix[j];
        }
d891 4
a894 7
      } else {
        imgpix = lin->imgpix;
        for (j = 0; j < n; j++) {
          pix[j] = lin->crpix[j];
          for (i = 0; i < n; i++) {
            pix[j] += *(imgpix++) * tmp[i];
          }
a911 200
}

/*--------------------------------------------------------------------------*/

int linwarp(
  struct linprm *lin,
  const double pixblc[],
  const double pixtrc[],
  const double pixsamp[],
  int    *nsamp,
  double maxdis[],
  double *maxtot,
  double avgdis[],
  double *avgtot,
  double rmsdis[],
  double *rmstot)

{
  static const char *function = "linwarp";

  int carry, i, j, naxis, ncoord, status = 0;
  double dpix, dpx2, dssq, *img, *pix0, *pix0p, *pix1, *pix1p, *pixend,
         *pixinc, pixspan, *ssqdis, ssqtot, *sumdis, sumtot, totdis;
  struct linprm affine;
  struct wcserr **err;


  /* Initialize. */
  if (lin == 0x0) return LINERR_NULL_POINTER;
  err = &(lin->err);

  naxis = lin->naxis;

  if (nsamp) *nsamp = 0;
  for (j = 0; j < naxis; j++) {
    if (maxdis) maxdis[j] = 0.0;
    if (avgdis) avgdis[j] = 0.0;
    if (rmsdis) rmsdis[j] = 0.0;
  }
  if (maxtot) *maxtot = 0.0;
  if (avgtot) *avgtot = 0.0;
  if (rmstot) *rmstot = 0.0;

  /* Quick return if no distortions. */
  if (lin->affine) return 0;

  /* It's easier if there are no sequent distortions! */
  if (lin->disseq == 0x0) {
    status = diswarp(lin->dispre, pixblc, pixtrc, pixsamp, nsamp,
                     maxdis, maxtot, avgdis, avgtot, rmsdis, rmstot);
    return wcserr_set(LIN_ERRMSG(lin_diserr[status]));
  }

  /* Make a reference copy of lin without distortions. */
  affine.flag = -1;
  if ((status = (lincpy(1, lin, &affine) ||
                 lindis(1, &affine, 0x0) ||
                 lindis(2, &affine, 0x0) ||
                 linset(&affine)))) {
    return wcserr_set(LIN_ERRMSG(status));
  }

  /* Work out increments on each axis. */
  pixinc = lin->tmpcrd;
  for (j = 0; j < naxis; j++) {
    pixspan = pixtrc[j] - (pixblc ? pixblc[j] : 1.0);

    if (pixsamp == 0x0) {
      pixinc[j] = 1.0;
    } else if (pixsamp[j] == 0.0) {
      pixinc[j] = 1.0;
    } else if (pixsamp[j] > 0.0) {
      pixinc[j] = pixsamp[j];
    } else if (pixsamp[j] > -1.5) {
      pixinc[j] = 2.0*pixspan;
    } else {
      pixinc[j] = pixspan / ((int)(-pixsamp[j] - 0.5));
    }

    if (j == 0) {
      /* Number of samples on axis 1. */
      ncoord = 1 + (int)((pixspan/pixinc[0]) + 0.5);
    }
  }

  /* Get memory for processing the image row by row. */
  if ((pix0 = calloc((3*ncoord+4)*naxis, sizeof(double))) == 0x0) {
    return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
  }

  img    = pix0 + naxis*ncoord;
  pix1   = img  + naxis*ncoord;
  pixinc = pix1 + naxis*ncoord;
  pixend = pixinc + naxis;
  sumdis = pixend + naxis;
  ssqdis = sumdis + naxis;


  /* Copy tmpcrd since linp2x() will overwrite it. */
  memcpy(pixinc, lin->tmpcrd, naxis*sizeof(double));

  /* Set up the array of pixel coordinates. */
  for (j = 0; j < naxis; j++) {
    pix0[j] = pixblc ? pixblc[j] : 1.0;
    pixend[j] = pixtrc[j] + 0.5*pixinc[j];
  }

  pix0p = pix0 + naxis;
  for (i = 1; i < ncoord; i++) {
    *(pix0p++) = pix0[0] + i*pixinc[0];

    for (j = 1; j < naxis; j++) {
      *(pix0p++) = pix0[j];
    }
  }

  /* Initialize accumulators. */
  for (j = 0; j < naxis; j++) {
    sumdis[j] = 0.0;
    ssqdis[j] = 0.0;
  }
  sumtot = 0.0;
  ssqtot = 0.0;


  /* Loop over N dimensions. */
  carry = 0;
  while (carry == 0) {
    if ((status = linp2x(lin, ncoord, naxis, pix0, img))) {
      wcserr_set(LIN_ERRMSG(status));
      goto cleanup;
    }

    if ((status = linx2p(&affine, ncoord, naxis, img, pix1))) {
      wcserr_set(LIN_ERRMSG(status));
      goto cleanup;
    }

    /* Accumulate statistics. */
    pix0p = pix0;
    pix1p = pix1;
    for (i = 0; i < ncoord; i++) {
      (*nsamp)++;

      dssq = 0.0;
      for (j = 0; j < naxis; j++) {
        dpix = *(pix1p++) - *(pix0p++);
        dpx2 = dpix*dpix;

        sumdis[j] += dpix;
        ssqdis[j] += dpx2;

        if (maxdis && (dpix = fabs(dpix)) > maxdis[j]) maxdis[j] = dpix;

        dssq += dpx2;
      }

      sumtot += totdis;
      ssqtot += totdis*totdis;

      totdis = sqrt(dssq);
      if (maxtot && *maxtot < totdis) *maxtot = totdis;
    }

    /* Next array of pixel coordinates. */
    for (j = 1; j < naxis; j++) {
      pix0[j] += pixinc[j];
      if ((carry = (pix0[j] > pixend[j]))) {
        pix0[j] = pixblc ? pixblc[j] : 1.0;
      }

      pix0p = pix0 + naxis + j;
      for (i = 1; i < ncoord; i++) {
        *pix0p = pix0[j];
        pix0p += naxis;
      }

      if (carry == 0) break;
    }
  }


  /* Compute the means and RMSs. */
  for (j = 0; j < naxis; j++) {
    ssqdis[j] /= *nsamp;
    sumdis[j] /= *nsamp;
    if (avgdis) avgdis[j] = sumdis[j];
    if (rmsdis) rmsdis[j] = sqrt(ssqdis[j] - sumdis[j]*sumdis[j]);
  }

  ssqtot /= *nsamp;
  sumtot /= *nsamp;
  if (avgtot) *avgtot = sumtot;
  if (rmstot) *rmstot = sqrt(ssqtot - sumtot*sumtot);


cleanup:
  free(pix0);

  return status;
@


4.25
log
@WCSLIB 4.25
@
text
@d3 2
a4 2
  WCSLIB 4.25 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2014, Mark Calabretta
d25 1
a25 1
  $Id: lin.c,v 4.24.1.1 2014/09/18 15:28:09 mcalabre Exp mcalabre $
d30 1
d36 1
d45 14
a58 1
  "PCi_ja matrix is singular"};
d65 1
a65 4
int linini(alloc, naxis, lin)

int alloc, naxis;
struct linprm *lin;
d86 13
a98 5
    lin->m_flag  = 0;
    lin->m_naxis = 0x0;
    lin->m_crpix = 0x0;
    lin->m_pc    = 0x0;
    lin->m_cdelt = 0x0;
a100 1

d107 8
d117 3
a119 3
     lin->crpix == 0x0 ||
     lin->pc    == 0x0 ||
     lin->cdelt == 0x0) {
d133 1
a133 1
        if (!(lin->crpix = calloc(naxis, sizeof(double)))) {
d149 1
a149 1
        if (!(lin->pc = calloc(naxis*naxis, sizeof(double)))) {
d166 1
a166 1
        if (!(lin->cdelt = calloc(naxis, sizeof(double)))) {
d178 11
d195 6
a200 3
  lin->piximg = 0x0;
  lin->imgpix = 0x0;
  lin->i_naxis = 0x0;
a210 1

a223 1

d235 38
a272 1
int lincpy(alloc, linsrc, lindst)
d274 3
a276 3
int alloc;
const struct linprm *linsrc;
struct linprm *lindst;
d320 39
a358 1
  return 0;
d363 1
a363 3
int linfree(lin)

struct linprm *lin;
d371 11
a381 3
      if (lin->crpix == lin->m_crpix) lin->crpix = 0x0;
      if (lin->pc    == lin->m_pc)    lin->pc    = 0x0;
      if (lin->cdelt == lin->m_cdelt) lin->cdelt = 0x0;
d383 9
a391 3
      if (lin->m_crpix) free(lin->m_crpix);
      if (lin->m_pc)    free(lin->m_pc);
      if (lin->m_cdelt) free(lin->m_cdelt);
d395 9
a403 5
  lin->m_flag  = 0;
  lin->m_naxis = 0;
  lin->m_crpix = 0x0;
  lin->m_pc    = 0x0;
  lin->m_cdelt = 0x0;
d412 2
a413 2
  lin->piximg = 0x0;
  lin->imgpix = 0x0;
d428 1
a428 3
int linprt(lin)

const struct linprm *lin;
d439 1
d441 1
a441 1
  wcsprintf("       flag: %d\n", lin->flag);
d443 1
d446 2
a447 2
  for (i = 0; i < lin->naxis; i++) {
    wcsprintf("  %- 11.5g", lin->crpix[i]);
d456 1
a456 1
      wcsprintf("  %- 11.5g", lin->pc[k++]);
d464 1
a464 1
    wcsprintf("  %- 11.5g", lin->cdelt[i]);
d468 6
a473 6
  wcsprintf("      unity: %d\n", lin->unity);

  WCSPRINTF_PTR("        err: ", lin->err, "\n");
  if (lin->err) {
    wcserr_prt(lin->err, "             ");
  }
d475 1
d483 1
a483 1
        wcsprintf("  %- 11.5g", lin->piximg[k++]);
d496 1
a496 1
        wcsprintf("  %- 11.5g", lin->imgpix[k++]);
d502 15
d528 19
d553 14
a566 1
int linset(lin)
d568 1
a568 1
struct linprm *lin;
d609 2
a610 2
    lin->piximg = 0x0;
    lin->imgpix = 0x0;
d622 1
a622 1
      if (!(lin->piximg = calloc(n*n, sizeof(double)))) {
d626 1
a626 1
      if (!(lin->imgpix = calloc(n*n, sizeof(double)))) {
d639 6
a644 1
        *(piximg++) = lin->cdelt[i] * (*(pc++));
d652 19
d673 2
d683 6
a688 1
int linp2x(lin, ncoord, nelem, pixcrd, imgcrd)
d690 2
a691 4
struct linprm *lin;
int ncoord, nelem;
const double pixcrd[];
double imgcrd[];
d693 1
a693 2
{
  int i, j, k, n, status;
d696 2
a697 1
  register double *img, *piximg;
d702 2
d715 3
a717 1
  if (lin->unity) {
d723 2
a724 2
      pix += (nelem - n);
      img += (nelem - n);
d727 4
a730 1
  } else {
d732 1
a732 3
      for (i = 0; i < n; i++) {
        img[i] = 0.0;
      }
d735 3
a739 2

        piximg = lin->piximg + j;
d745 49
a793 1
      pix += (nelem - n);
d803 6
a808 1
int linx2p(lin, ncoord, nelem, imgcrd, pixcrd)
d810 2
a811 4
struct linprm *lin;
int ncoord, nelem;
const double imgcrd[];
double pixcrd[];
d813 1
a813 2
{
  int i, j, k, n, status;
d815 2
a816 1
  register double *imgpix, *pix;
d821 2
d834 3
a836 1
  if (lin->unity) {
d842 2
a843 2
      pix += (nelem - n);
      img += (nelem - n);
d846 3
a848 1
  } else {
d850 1
a862 1
      pix += (nelem - n);
d864 44
d925 1
a925 1
  if (!(mxl = calloc(n, sizeof(int)))) {
d928 1
a928 1
  if (!(lxm = calloc(n, sizeof(int)))) {
d933 1
a933 1
  if (!(rowmax = calloc(n, sizeof(double)))) {
d939 1
a939 1
  if (!(lu = calloc(n*n, sizeof(double)))) {
@


4.25.1.1
log
@WCSLIB 4.25 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 4.25 2014/12/14 14:29:36 mcalabre Exp $
@


4.25.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2015, Mark Calabretta
d25 1
a25 1
  $Id: lin.c,v 4.25.1.1 2014/12/14 14:32:45 mcalabre Exp mcalabre $
@


4.25.1.3
log
@Major development to include distortion functions in the algorithm chain
transforming between pixel coordinates and intermediate world coordinates.
ABI changed due to changes in the linprm struct.  New functions lindis()
and linperr().  Tweaked output formatting in linprt().  ANSIfied function
definitions.
@
text
@d25 1
a25 1
  $Id: lin.c,v 4.25.1.2 2015/01/06 01:01:06 mcalabre Exp mcalabre $
a29 1
#include <string.h>
a34 1
#include "dis.h"
d43 1
a43 14
  "PCi_ja matrix is singular",
  "Failed to initialize distortion functions",
  "Distort error",
  "De-distort error"};

/* Map error returns for lower-level routines. */
const int lin_diserr[] = {
  LINERR_SUCCESS,		/*  0: DISERR_SUCCESS         */
  LINERR_NULL_POINTER,		/*  1: DISERR_NULL_POINTER    */
  LINERR_MEMORY,		/*  2: DISERR_MEMORY          */
  LINERR_DISTORT_INIT,		/*  3: DISERR_BAD_PARAM       */
  LINERR_DISTORT,		/*  4: DISERR_DISTORT         */
  LINERR_DEDISTORT		/*  5: DISERR_DEDISTORT       */
};
d50 4
a53 1
int linini(int alloc, int naxis, struct linprm *lin)
d74 6
a79 5
    if (lin->flag == -1) {
      lin->dispre = 0x0;
      lin->disseq = 0x0;
      lin->tmpcrd = 0x0;
    }
a80 8
    lin->m_flag   = 0;
    lin->m_naxis  = 0;
    lin->m_crpix  = 0x0;
    lin->m_pc     = 0x0;
    lin->m_cdelt  = 0x0;
    lin->m_dispre = 0x0;
    lin->m_disseq = 0x0;
  }
a87 8
  /* Create work arrays. */
  if (lin->tmpcrd) free(lin->tmpcrd);
  if ((lin->tmpcrd = calloc(naxis, sizeof(double))) == 0x0) {
    linfree(lin);
    return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
  }


d90 3
a92 3
      lin->crpix  == 0x0 ||
      lin->pc     == 0x0 ||
      lin->cdelt  == 0x0) {
d106 1
a106 1
        if ((lin->crpix = calloc(naxis, sizeof(double))) == 0x0) {
d122 1
a122 1
        if ((lin->pc = calloc(naxis*naxis, sizeof(double))) == 0x0) {
d139 1
a139 1
        if ((lin->cdelt = calloc(naxis, sizeof(double))) == 0x0) {
a150 11

  /* Reinitialize disprm structs if we are managing them. */
  if (lin->m_dispre) {
    disini(1, naxis, lin->dispre);
  }

  if (lin->m_disseq) {
    disini(1, naxis, lin->disseq);
  }


d157 3
a159 6
  lin->piximg  = 0x0;
  lin->imgpix  = 0x0;
  lin->i_naxis = 0;
  lin->unity   = 0;
  lin->affine  = 0;
  lin->simple  = 0;
d170 1
d184 1
d196 1
a196 38
int lindis(int sequence, struct linprm *lin, struct disprm *dis)

{
  static const char *function = "lindis";

  int status;
  struct wcserr **err;

  if (lin == 0x0) return LINERR_NULL_POINTER;
  err = &(lin->err);

  if (sequence == 1) {
    if (lin->m_dispre) free(lin->m_dispre);

    lin->dispre   = dis;
    lin->m_flag   = LINSET;
    lin->m_dispre = dis;

  } else if (sequence == 2) {
    if (lin->m_disseq) free(lin->m_disseq);

    lin->disseq   = dis;
    lin->m_flag   = LINSET;
    lin->m_disseq = dis;

  } else {
    return wcserr_set(WCSERR_SET(LINERR_DISTORT_INIT),
      "Invalid sequence (%d)", sequence);
  }

  if (dis) {
    if ((status = disini(1, lin->naxis, dis))) {
      return wcserr_set(LIN_ERRMSG(lin_diserr[status]));
    }
  }

  return 0;
}
d198 3
a200 3
/*--------------------------------------------------------------------------*/

int lincpy(int alloc, const struct linprm *linsrc, struct linprm *lindst)
d244 1
a244 39
  if (linsrc->dispre) {
    if (!lindst->dispre) {
      if ((lindst->dispre = calloc(1, sizeof(struct disprm))) == 0x0) {
        return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
      }

      lindst->m_dispre = lindst->dispre;
    }

    if ((status = discpy(alloc, linsrc->dispre, lindst->dispre))) {
      status = wcserr_set(LIN_ERRMSG(lin_diserr[status]));
      goto cleanup;
    }
  }

  if (linsrc->disseq) {
    if (!lindst->disseq) {
      if ((lindst->disseq = calloc(1, sizeof(struct disprm))) == 0x0) {
        return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
      }

      lindst->m_disseq = lindst->disseq;
    }

    if ((status = discpy(alloc, linsrc->disseq, lindst->disseq))) {
      status = wcserr_set(LIN_ERRMSG(lin_diserr[status]));
      goto cleanup;
    }
  }

cleanup:
  if (status && (lindst->m_dispre || lindst->m_disseq)) {
    if (lindst->dispre) free(lindst->dispre);
    if (lindst->disseq) free(lindst->disseq);
    lindst->dispre = 0x0;
    lindst->disseq = 0x0;
  }

  return status;
d249 3
a251 1
int linfree(struct linprm *lin)
d259 3
a261 11
      if (lin->crpix  == lin->m_crpix)  lin->crpix  = 0x0;
      if (lin->pc     == lin->m_pc)     lin->pc     = 0x0;
      if (lin->cdelt  == lin->m_cdelt)  lin->cdelt  = 0x0;
      if (lin->dispre == lin->m_dispre) lin->dispre = 0x0;
      if (lin->disseq == lin->m_disseq) lin->disseq = 0x0;

      if (lin->tmpcrd)   free(lin->tmpcrd);

      if (lin->m_crpix)  free(lin->m_crpix);
      if (lin->m_pc)     free(lin->m_pc);
      if (lin->m_cdelt)  free(lin->m_cdelt);
d263 3
a265 9
      if (lin->m_dispre) {
        disfree(lin->m_dispre);
        free(lin->m_dispre);
      }

      if (lin->m_disseq) {
        disfree(lin->m_disseq);
        free(lin->m_disseq);
      }
d269 5
a273 9
  lin->tmpcrd   = 0x0;

  lin->m_flag   = 0;
  lin->m_naxis  = 0;
  lin->m_crpix  = 0x0;
  lin->m_pc     = 0x0;
  lin->m_cdelt  = 0x0;
  lin->m_dispre = 0x0;
  lin->m_disseq = 0x0;
d282 2
a283 2
  lin->piximg  = 0x0;
  lin->imgpix  = 0x0;
d298 3
a300 1
int linprt(const struct linprm *lin)
d311 1
a312 2

  /* Parameters supplied. */
a313 1

d316 2
a317 2
  for (j = 0; j < lin->naxis; j++) {
    wcsprintf("  %#- 11.5g", lin->crpix[j]);
d326 1
a326 1
      wcsprintf("  %#- 11.5g", lin->pc[k++]);
d334 1
a334 1
    wcsprintf("  %#- 11.5g", lin->cdelt[i]);
d338 6
a343 6
  WCSPRINTF_PTR("     dispre: ", lin->dispre, "");
  if (lin->dispre != 0x0) wcsprintf("  (see below)");
  wcsprintf("\n");
  WCSPRINTF_PTR("     disseq: ", lin->disseq, "");
  if (lin->disseq != 0x0) wcsprintf("  (see below)");
  wcsprintf("\n");
a344 1
  /* Derived values. */
d352 1
a352 1
        wcsprintf("  %#- 11.5g", lin->piximg[k++]);
d365 1
a365 1
        wcsprintf("  %#- 11.5g", lin->imgpix[k++]);
a370 15
  wcsprintf("    i_naxis: %d\n", lin->i_naxis);
  wcsprintf("      unity: %d\n", lin->unity);
  wcsprintf("     affine: %d\n", lin->affine);
  wcsprintf("     simple: %d\n", lin->simple);

  /* Error handling. */
  WCSPRINTF_PTR("        err: ", lin->err, "\n");
  if (lin->err) {
    wcserr_prt(lin->err, "             ");
  }

  /* Work arrays. */
  WCSPRINTF_PTR("     tmpcrd: ", lin->tmpcrd, "\n");

  /* Memory management. */
a381 19
  WCSPRINTF_PTR("   m_dispre: ", lin->m_dispre, "");
  if (lin->dispre && lin->m_dispre == lin->dispre) wcsprintf("  (= dispre)");
  wcsprintf("\n");
  WCSPRINTF_PTR("   m_disseq: ", lin->m_disseq, "");
  if (lin->disseq && lin->m_disseq == lin->disseq) wcsprintf("  (= disseq)");
  wcsprintf("\n");

  /* Distortion parameters (from above). */
  if (lin->dispre) {
    wcsprintf("\n");
    wcsprintf("dispre.*\n");
    disprt(lin->dispre);
  }

  if (lin->disseq) {
    wcsprintf("\n");
    wcsprintf("disseq.*\n");
    disprt(lin->disseq);
  }
d388 1
a388 14
int linperr(const struct linprm *lin, const char *prefix)

{
  if (lin == 0x0) return LINERR_NULL_POINTER;

  if (!wcserr_prt(lin->err, prefix)) {
    if (lin->dispre) wcserr_prt(lin->dispre->err, prefix);
    if (lin->disseq) wcserr_prt(lin->disseq->err, prefix);
  }

  return 0;
}

/*--------------------------------------------------------------------------*/
d390 1
a390 1
int linset(struct linprm *lin)
d431 2
a432 2
    lin->piximg  = 0x0;
    lin->imgpix  = 0x0;
d444 1
a444 1
      if ((lin->piximg = calloc(n*n, sizeof(double))) == 0x0) {
d448 1
a448 1
      if ((lin->imgpix = calloc(n*n, sizeof(double))) == 0x0) {
d461 1
a461 6
        if (lin->disseq == 0x0) {
          /* No sequent distortions, incorporate cdelt into piximg. */
          *(piximg++) = lin->cdelt[i] * (*(pc++));
        } else {
          *(piximg++) = *(pc++);
        }
a468 19


    /* Set up the distortion functions. */
    lin->affine = 1;
    if (lin->dispre) {
      if ((status = disset(lin->dispre))) {
        return wcserr_set(LIN_ERRMSG(lin_diserr[status]));
      }

      lin->affine = 0;
    }

    if (lin->disseq) {
      if ((status = disset(lin->disseq))) {
        return wcserr_set(LIN_ERRMSG(lin_diserr[status]));
      }

      lin->affine = 0;
    }
a470 2
  lin->simple = lin->unity && lin->affine;

d479 6
a484 6
int linp2x(
  struct linprm *lin,
  int ncoord,
  int nelem,
  const double pixcrd[],
  double imgcrd[])
d487 1
a487 3
  static const char *function = "linp2x";

  int i, j, k, n, ndbl, nelemn, status;
d490 1
a490 2
  register double *img, *piximg, *tmp;
  struct wcserr **err;
a494 2
  err = &(lin->err);

d506 1
a506 3
  if (lin->simple) {
    /* Handle the simplest and most common case with maximum efficiency. */
    nelemn = nelem - n;
d512 2
a513 2
      pix += nelemn;
      img += nelemn;
d516 1
a516 4
  } else if (lin->affine) {
    /* No distortions. */
    ndbl   = n * sizeof(double);
    nelemn = nelem - n;
d518 3
a520 1
      memset(img, 0, ndbl);
a522 3
        /* cdelt will have been incorporated into piximg. */
        piximg = lin->piximg + j;

d525 2
d532 1
a532 49
      pix += nelemn;
      img += nelem;
    }

  } else {
    /* Distortions are present. */
    ndbl = n * sizeof(double);
    tmp  = lin->tmpcrd;

    for (k = 0; k < ncoord; k++) {
      if (lin->dispre) {
        if ((status = disp2x(lin->dispre, pix, tmp))) {
          return wcserr_set(LIN_ERRMSG(lin_diserr[status]));
        }
      } else {
        memcpy(tmp, pix, ndbl);
      }

      if (lin->unity) {
        for (i = 0; i < n; i++) {
          img[i] = lin->cdelt[i] * (tmp[i] - lin->crpix[i]);
        }

      } else {
        for (j = 0; j < n; j++) {
          tmp[j] -= lin->crpix[j];
        }

        piximg = lin->piximg;
        for (i = 0; i < n; i++) {
          img[i] = 0.0;
          for (j = 0; j < n; j++) {
            img[i] += *(piximg++) * tmp[j];
          }
        }
      }

      if (lin->disseq) {
        if ((status = disp2x(lin->disseq, img, tmp))) {
          return wcserr_set(LIN_ERRMSG(lin_diserr[status]));
        }

        /* With sequent distortions, cdelt is not incorporated into piximg. */
        for (i = 0; i < n; i++) {
          img[i] = lin->cdelt[i] * tmp[i];
        }
      }

      pix += nelem;
d542 6
a547 6
int linx2p(
  struct linprm *lin,
  int ncoord,
  int nelem,
  const double imgcrd[],
  double pixcrd[])
d550 1
a550 3
  static const char *function = "linx2p";

  int i, j, k, n, ndbl, nelemn, status;
d552 1
a552 2
  register double *imgpix, *pix, *tmp;
  struct wcserr **err;
a556 2
  err = &(lin->err);

d568 1
a568 3
  if (lin->simple) {
    /* Handle the simplest and most common case with maximum efficiency. */
    nelemn = nelem - n;
d574 2
a575 2
      img += nelemn;
      pix += nelemn;
d578 1
a578 3
  } else if (lin->affine) {
    /* No distortions. */
    nelemn = nelem - n;
a579 1
      /* cdelt will have been incorporated into imgpix. */
d592 1
a593 44
      pix += nelemn;
    }

  } else {
    /* Distortions are present. */
    ndbl = n * sizeof(double);
    tmp  = lin->tmpcrd;

    for (k = 0; k < ncoord; k++) {
      if (lin->disseq) {
        /* With sequent distortions, cdelt is not incorporated into imgpix. */
        for (i = 0; i < n; i++) {
          tmp[i] = img[i] / lin->cdelt[i];
        }

        if ((status = disx2p(lin->disseq, tmp, pix))) {
          return wcserr_set(LIN_ERRMSG(lin_diserr[status]));
        }

        memcpy(tmp, pix, ndbl);

      } else {
        memcpy(tmp, img, ndbl);
      }

      imgpix = lin->imgpix;

      for (j = 0; j < n; j++) {
        pix[j] = lin->crpix[j];
        for (i = 0; i < n; i++) {
          pix[j] += *(imgpix++) * tmp[i];
        }
      }

      if (lin->dispre) {
        memcpy(tmp, pix, ndbl);

        if ((status = disx2p(lin->dispre, tmp, pix))) {
          return wcserr_set(LIN_ERRMSG(lin_diserr[status]));
        }
      }

      img += nelem;
      pix += nelem;
d611 1
a611 1
  if ((mxl = calloc(n, sizeof(int))) == 0x0) {
d614 1
a614 1
  if ((lxm = calloc(n, sizeof(int))) == 0x0) {
d619 1
a619 1
  if ((rowmax = calloc(n, sizeof(double))) == 0x0) {
d625 1
a625 1
  if ((lu = calloc(n*n, sizeof(double))) == 0x0) {
@


4.25.1.4
log
@linperr() mustn't attempt to report errors from lin->dispre or lin->disseq
unless lin->err itself has been set.  Refer to comments for wcs.c v4.25.1.5.
@
text
@d25 1
a25 1
  $Id: lin.c,v 4.25.1.3 2015/04/03 02:22:45 mcalabre Exp mcalabre $
d558 1
a558 1
  if (lin->err && wcserr_prt(lin->err, prefix) == 0) {
@


4.24
log
@WCSLIB 4.24
@
text
@d3 1
a3 1
  WCSLIB 4.24 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 4.23.1.1 2014/05/13 05:53:49 mcalabre Exp mcalabre $
@


4.24.1.1
log
@WCSLIB 4.24 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 4.24 2014/09/18 15:25:00 mcalabre Exp $
@


4.23
log
@WCSLIB 4.23
@
text
@d3 1
a3 1
  WCSLIB 4.23 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 4.22.1.1 2014/04/12 15:06:32 mcalabre Exp mcalabre $
@


4.23.1.1
log
@WCSLIB 4.23 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 4.23 2014/05/13 05:50:51 mcalabre Exp $
@


4.22
log
@WCSLIB 4.22
@
text
@d3 1
a3 1
  WCSLIB 4.22 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 4.21.1.1 2014/03/24 05:15:28 mcalabre Exp mcalabre $
@


4.22.1.1
log
@WCSLIB 4.22 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 4.22 2014/04/12 15:03:52 mcalabre Exp $
@


4.21
log
@WCSLIB 4.21
@
text
@d3 1
a3 1
  WCSLIB 4.21 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 4.20.1.2 2014/03/21 06:32:19 mcalabre Exp mcalabre $
@


4.21.1.1
log
@WCSLIB 4.21 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 4.21 2014/03/24 05:12:27 mcalabre Exp $
@


4.20
log
@WCSLIB 4.20
@
text
@d3 2
a4 2
  WCSLIB 4.20 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2013, Mark Calabretta
d25 1
a25 1
  $Id: lin.c,v 4.19.1.1 2013/09/29 14:20:38 mcalabre Exp mcalabre $
@


4.20.1.1
log
@WCSLIB 4.20 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 4.20 2013/12/18 05:42:49 mcalabre Exp $
@


4.20.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2014, Mark Calabretta
d25 1
a25 1
  $Id: lin.c,v 4.20.1.1 2013/12/18 05:46:55 mcalabre Exp mcalabre $
@


4.19
log
@WCSLIB 4.19
@
text
@d3 1
a3 1
  WCSLIB 4.19 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 4.18.1.1 2013/07/13 10:02:37 mcalabre Exp mcalabre $
@


4.19.1.1
log
@WCSLIB 4.19 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 4.19 2013/09/29 14:17:51 mcalabre Exp $
@


4.18
log
@WCSLIB 4.18
@
text
@d3 1
a3 1
  WCSLIB 4.18 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 4.17.1.1 2013/01/29 05:32:32 cal103 Exp cal103 $
@


4.18.1.1
log
@WCSLIB 4.18 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 4.18 2013/07/13 10:00:04 mcalabre Exp $
@


4.17
log
@WCSLIB 4.17
@
text
@d3 1
a3 1
  WCSLIB 4.17 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 4.16.1.2 2013/01/29 05:09:44 cal103 Exp cal103 $
@


4.17.1.1
log
@WCSLIB 4.17 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 4.17 2013/01/29 05:29:20 cal103 Exp $
@


4.16
log
@WCSLIB 4.16
@
text
@d3 2
a4 2
  WCSLIB 4.16 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2012, Mark Calabretta
d25 1
a25 1
  $Id: lin.c,v 4.15.1.1 2012/09/26 14:27:51 cal103 Exp cal103 $
@


4.16.1.1
log
@WCSLIB 4.16 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 4.16 2012/11/07 04:42:44 cal103 Exp $
@


4.16.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2013, Mark Calabretta
d25 1
a25 1
  $Id: lin.c,v 4.16.1.1 2012/11/07 04:45:56 cal103 Exp cal103 $
@


4.15
log
@WCSLIB 4.15
@
text
@d3 1
a3 1
  WCSLIB 4.15 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 4.14.1.1 2012/07/13 10:04:44 cal103 Exp cal103 $
@


4.15.1.1
log
@WCSLIB 4.15 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 4.15 2012/09/26 14:26:05 cal103 Exp $
@


4.14
log
@WCSLIB 4.14
@
text
@d3 1
a3 1
  WCSLIB 4.14 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: lin.c,v 4.13.1.2 2012/07/13 03:34:20 cal103 Exp cal103 $
@


4.14.1.1
log
@WCSLIB 4.14 development branch.
@
text
@d25 1
a25 1
  $Id: lin.c,v 4.14 2012/07/13 10:02:27 cal103 Exp $
@


4.13
log
@WCSLIB 4.13
@
text
@d3 1
a3 1
  WCSLIB 4.13 - an implementation of the FITS WCS standard.
d19 1
a19 1
  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
d21 5
a25 11
  Correspondence concerning WCSLIB may be directed to:
    Internet email: mcalabre@@atnf.csiro.au
    Postal address: Dr. Mark Calabretta
                    Australia Telescope National Facility, CSIRO
                    PO Box 76
                    Epping NSW 1710
                    AUSTRALIA

  Author: Mark Calabretta, Australia Telescope National Facility
  http://www.atnf.csiro.au/~mcalabre/index.html
  $Id: lin.c,v 4.12.1.2 2012/03/14 06:41:42 cal103 Exp cal103 $
@


4.13.1.1
log
@WCSLIB 4.13 development branch.
@
text
@d31 1
a31 1
  $Id: lin.c,v 4.13 2012/03/14 07:39:30 cal103 Exp $
@


4.13.1.2
log
@Changed contact details.
@
text
@d19 1
a19 1
  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
d21 11
a31 5
  Direct correspondence concerning WCSLIB to mark@@calabretta.id.au

  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
  http://www.atnf.csiro.au/people/Mark.Calabretta
  $Id: lin.c,v 4.13.1.1 2012/03/14 07:40:37 cal103 Exp cal103 $
@


4.12
log
@WCSLIB 4.12
@
text
@d3 1
a3 1
  WCSLIB 4.12 - an implementation of the FITS WCS standard.
d31 1
a31 1
  $Id: lin.c,v 4.11.1.1 2012/02/20 23:31:13 cal103 Exp cal103 $
d88 1
a88 1
  if (naxis < 1) {
d90 1
a90 1
      "naxis must be positive (got %d)", naxis);
d292 4
a295 2
  if (lin->err) free(lin->err);
  lin->err = 0x0;
@


4.12.1.1
log
@WCSLIB 4.12 development branch.
@
text
@d31 1
a31 1
  $Id: lin.c,v 4.12 2012/02/29 07:57:56 cal103 Exp $
@


4.12.1.2
log
@In linini(), allow naxis to be zero for a completely degenerate coordinate
system as may be produced by wcssub().
@
text
@d31 1
a31 1
  $Id: lin.c,v 4.12.1.1 2012/02/29 07:59:10 cal103 Exp cal103 $
d88 1
a88 1
  if (naxis < 0) {
d90 1
a90 1
      "naxis must not be negative (got %d)", naxis);
d292 2
a293 4
  if (lin->err) {
    free(lin->err);
    lin->err = 0x0;
  }
@


4.11
log
@WCSLIB 4.11
@
text
@d3 1
a3 1
  WCSLIB 4.11 - an implementation of the FITS WCS standard.
d31 1
a31 1
  $Id: lin.c,v 4.10.1.1 2012/02/05 23:42:46 cal103 Exp cal103 $
@


4.11.1.1
log
@WCSLIB 4.11 development branch.
@
text
@d31 1
a31 1
  $Id: lin.c,v 4.11 2012/02/20 23:30:02 cal103 Exp $
@


4.10
log
@WCSLIB 4.10
@
text
@d3 1
a3 1
  WCSLIB 4.10 - an implementation of the FITS WCS standard.
d31 1
a31 1
  $Id: lin.c,v 4.9.1.1 2012/01/24 05:41:45 cal103 Exp cal103 $
@


4.10.1.1
log
@WCSLIB 4.10 development branch.
@
text
@d31 1
a31 1
  $Id: lin.c,v 4.10 2012/02/05 23:41:44 cal103 Exp $
@


4.9
log
@WCSLIB 4.9
@
text
@d3 1
a3 1
  WCSLIB 4.9 - an implementation of the FITS WCS standard.
d31 1
a31 1
  $Id: lin.c,v 4.8.1.3 2012/01/24 05:23:06 cal103 Exp cal103 $
@


4.9.1.1
log
@WCSLIB 4.9 development branch.
@
text
@d31 1
a31 1
  $Id: lin.c,v 4.9 2012/01/24 05:40:29 cal103 Exp $
@


4.8
log
@WCSLIB 4.8
@
text
@d3 2
a4 2
  WCSLIB 4.8 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2011, Mark Calabretta
d31 1
a31 1
  $Id: lin.c,v 4.7.1.5 2011/08/12 05:42:29 cal103 Exp cal103 $
d346 1
a346 1
    wcserr_prt(lin->err, "");
@


4.8.1.1
log
@WCSLIB 4.8 development branch.
@
text
@d31 1
a31 1
  $Id: lin.c,v 4.8 2011/08/15 08:05:53 cal103 Exp $
@


4.8.1.2
log
@Minor refinement in linprt() for printing linprm::err.
@
text
@d31 1
a31 1
  $Id: lin.c,v 4.8.1.1 2011/08/15 08:07:06 cal103 Exp cal103 $
d346 1
a346 1
    wcserr_prt(lin->err, "             ");
@


4.8.1.3
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2012, Mark Calabretta
d31 1
a31 1
  $Id: lin.c,v 4.8.1.2 2011/11/17 03:07:49 cal103 Exp cal103 $
@


4.7
log
@WCSLIB 4.7
@
text
@d3 1
a3 1
  WCSLIB 4.7 - an implementation of the FITS WCS standard.
d31 1
a31 1
  $Id: lin.c,v 4.6.1.3 2011/01/25 00:35:11 cal103 Exp cal103 $
d38 1
d46 2
a47 2
   "Success",
   "Null linprm pointer passed",
d51 2
d62 2
d66 3
d70 4
a73 3
  if (lin == 0x0) return 1;
  if (naxis <= 0) {
    return 2;
d75 2
d78 1
d88 6
d113 1
a113 1
          return 2;
d130 1
a130 1
          return 2;
d147 1
a147 1
          return 2;
a166 1

d209 2
d214 1
d216 3
a218 1
  if (linsrc == 0x0) return 1;
d221 3
a223 2
  if (naxis <= 0) {
    return 2;
d260 1
a260 1
  if (lin == 0x0) return 1;
d292 3
d309 1
a309 1
  if (lin == 0x0) return 1;
d318 1
a318 1
  wcsprintf("      crpix: %p\n", (void *)lin->crpix);
d326 1
a326 1
  wcsprintf("         pc: %p\n", (void *)lin->pc);
d335 1
a335 1
  wcsprintf("      cdelt: %p\n", (void *)lin->cdelt);
d344 5
d377 1
a377 1
  wcsprintf("    m_crpix: %p", (void *)lin->m_crpix);
d380 1
a380 1
  wcsprintf("       m_pc: %p", (void *)lin->m_pc);
d383 1
a383 1
  wcsprintf("    m_cdelt: %p", (void *)lin->m_cdelt);
d397 2
d401 1
d403 2
a404 1
  if (lin == 0x0) return 1;
d449 1
a449 1
        return 2;
d454 1
a454 1
        return 2;
d471 1
a471 1
      return status;
d498 1
a498 1
  if (lin == 0x0) return 1;
d560 1
a560 1
  if (lin == 0x0) return 1;
d606 1
a606 5
int matinv(n, mat, inv)

int n;
const double mat[];
double inv[];
d615 3
a617 1
  if (!(mxl = calloc(n, sizeof(int)))) return 2;
d620 1
a620 1
    return 2;
d626 1
a626 1
    return 2;
d633 1
a633 1
    return 2;
d657 1
a657 1
      return 3;
@


4.7.1.1
log
@WCSLIB 4.7 development branch.
@
text
@d31 1
a31 1
  $Id: lin.c,v 4.7 2011/02/07 07:03:42 cal103 Exp $
@


4.7.1.2
log
@Added error messaging based on wcserr.  Changes supplied by Michael
Droettboom (STScI) with respect to the released WCSLIB 4.7 sources.
@
text
@d45 2
a46 2
  "Success",
  "Null linprm pointer passed",
d50 1
d62 1
a62 4
  if (lin == 0x0) return LINERR_NULL_POINTER;

  wcserr_ini(&lin->err);
  
d64 1
a64 3
    return WCSERR_SET(
      &lin->err, LINERR_MEMORY,
      "naxis must be positive (got %d)", naxis);
d95 1
a95 1
          return WCSERR_SET(&lin->err, LINERR_MEMORY, lin_errmsg[LINERR_MEMORY]);
d112 1
a112 1
          return WCSERR_SET(&lin->err, LINERR_MEMORY, lin_errmsg[LINERR_MEMORY]);
d129 1
a129 1
          return WCSERR_SET(&lin->err, LINERR_MEMORY, lin_errmsg[LINERR_MEMORY]);
d196 1
a196 1
  if (linsrc == 0x0) return LINERR_NULL_POINTER;
d200 1
a200 3
    return WCSERR_SET(
      &lindst->err, LINERR_MEMORY,
      "naxis must be positive (got %d)", naxis);
d237 1
a237 1
  if (lin == 0x0) return LINERR_NULL_POINTER;
d283 1
a283 1
  if (lin == 0x0) return LINERR_NULL_POINTER;
d369 1
a369 1
  if (lin == 0x0) return LINERR_NULL_POINTER;
d414 1
a414 1
        return WCSERR_SET(&lin->err, LINERR_MEMORY, lin_errmsg[LINERR_MEMORY]);
d419 1
a419 1
        return WCSERR_SET(&lin->err, LINERR_MEMORY, lin_errmsg[LINERR_MEMORY]);
d436 1
a436 1
      return WCSERR_SET(&lin->err, status, lin_errmsg[status]);
d463 1
a463 1
  if (lin == 0x0) return LINERR_NULL_POINTER;
d525 1
a525 1
  if (lin == 0x0) return LINERR_NULL_POINTER;
d571 5
a575 1
int matinv(int n, const double mat[], double inv[])
d584 1
a584 3
  if (!(mxl = calloc(n, sizeof(int)))) {
    return LINERR_MEMORY;
  }
d587 1
a587 1
    return LINERR_MEMORY;
d593 1
a593 1
    return LINERR_MEMORY;
d600 1
a600 1
    return LINERR_MEMORY;
d624 1
a624 1
      return LINERR_SINGULAR_MTX;
a720 1

@


4.7.1.3
log
@Revised implementation of Michael Droettboom's error messaging system.
@
text
@d31 1
a31 1
  $Id: lin.c,v 4.7.1.1 2011/02/07 07:04:22 cal103 Exp cal103 $
a37 1
#include "wcserr.h"
a49 3
/* Convenience macro for invoking wcserr_set(). */
#define LIN_ERRMSG(status) WCSERR_SET(status), lin_errmsg[status]

a57 2
  static const char *function = "linini";

a59 1
  struct wcserr **err;
d63 6
a68 4
  /* Initialize error message handling. */
  err = &(lin->err);
  if (lin->flag != -1) {
    if (lin->err) free(lin->err);
a69 1
  lin->err = 0x0;
a70 2

  /* Initialize memory management. */
a79 6
  if (naxis <= 0) {
    return wcserr_set(WCSERR_SET(LINERR_MEMORY),
      "naxis must be positive (got %d)", naxis);
  }


d99 1
a99 1
          return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
d116 1
a116 1
          return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
d133 1
a133 1
          return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
d153 1
a195 2
  static const char *function = "lincpy";

a198 1
  struct wcserr **err;
a200 2
  if (lindst == 0x0) return LINERR_NULL_POINTER;
  err = &(lindst->err);
d204 2
a205 1
    return wcserr_set(WCSERR_SET(LINERR_MEMORY),
a274 3
  if (lin->err) free(lin->err);
  lin->err = 0x0;

a323 5
  wcsprintf("        err: %p\n", (void *)lin->err);
  if (lin->err) {
    wcserr_prt(lin->err, "");
  }

a371 2
  static const char *function = "linset";

a373 1
  struct wcserr **err;
a375 1
  err = &(lin->err);
d420 1
a420 1
        return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
d425 1
a425 1
        return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
d442 1
a442 1
      return wcserr_set(LIN_ERRMSG(status));
d725 1
@


4.7.1.4
log
@Trivial tweak.
@
text
@d31 1
a31 1
  $Id: lin.c,v 4.7.1.3 2011/08/09 02:43:50 cal103 Exp cal103 $
d88 1
a88 1
  if (naxis < 1) {
d221 1
a221 1
  if (naxis < 1) {
@


4.7.1.5
log
@Use the WCSPRINTF_PTR() macro for printing addresses.
@
text
@d31 1
a31 1
  $Id: lin.c,v 4.7.1.4 2011/08/10 04:17:02 cal103 Exp cal103 $
d318 1
a318 1
  WCSPRINTF_PTR("      crpix: ", lin->crpix, "\n");
d326 1
a326 1
  WCSPRINTF_PTR("         pc: ", lin->pc, "\n");
d335 1
a335 1
  WCSPRINTF_PTR("      cdelt: ", lin->cdelt, "\n");
d344 1
a344 1
  WCSPRINTF_PTR("        err: ", lin->err, "\n");
d377 1
a377 1
  WCSPRINTF_PTR("    m_crpix: ", lin->m_crpix, "");
d380 1
a380 1
  WCSPRINTF_PTR("       m_pc: ", lin->m_pc, "");
d383 1
a383 1
  WCSPRINTF_PTR("    m_cdelt: ", lin->m_cdelt, "");
@


4.6
log
@WCSLIB 4.6
@
text
@d3 2
a4 2
  WCSLIB 4.6 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2010, Mark Calabretta
d31 1
a31 1
  $Id: lin.c,v 4.5.1.1 2010/07/16 07:05:31 cal103 Exp cal103 $
d37 2
d286 1
a286 1
    printf("The linprm struct is UNINITIALIZED.\n");
d290 4
a293 4
  printf("       flag: %d\n", lin->flag);
  printf("      naxis: %d\n", lin->naxis);
  printf("      crpix: %p\n", (void *)lin->crpix);
  printf("            ");
d295 1
a295 1
    printf("  %- 11.5g", lin->crpix[i]);
d297 1
a297 1
  printf("\n");
d300 1
a300 1
  printf("         pc: %p\n", (void *)lin->pc);
d302 1
a302 1
    printf("    pc[%d][]:", i);
d304 1
a304 1
      printf("  %- 11.5g", lin->pc[k++]);
d306 1
a306 1
    printf("\n");
d309 2
a310 2
  printf("      cdelt: %p\n", (void *)lin->cdelt);
  printf("            ");
d312 1
a312 1
    printf("  %- 11.5g", lin->cdelt[i]);
d314 1
a314 1
  printf("\n");
d316 1
a316 1
  printf("      unity: %d\n", lin->unity);
d319 1
a319 1
    printf("     piximg: (nil)\n");
d323 1
a323 1
      printf("piximg[%d][]:", i);
d325 1
a325 1
        printf("  %- 11.5g", lin->piximg[k++]);
d327 1
a327 1
      printf("\n");
d332 1
a332 1
    printf("     imgpix: (nil)\n");
d336 1
a336 1
      printf("imgpix[%d][]:", i);
d338 1
a338 1
        printf("  %- 11.5g", lin->imgpix[k++]);
d340 1
a340 1
      printf("\n");
d344 11
a354 11
  printf("     m_flag: %d\n", lin->m_flag);
  printf("    m_naxis: %d\n", lin->m_naxis);
  printf("    m_crpix: %p", (void *)lin->m_crpix);
  if (lin->m_crpix == lin->crpix) printf("  (= crpix)");
  printf("\n");
  printf("       m_pc: %p", (void *)lin->m_pc);
  if (lin->m_pc == lin->pc) printf("  (= pc)");
  printf("\n");
  printf("    m_cdelt: %p", (void *)lin->m_cdelt);
  if (lin->m_cdelt == lin->cdelt) printf("  (= cdelt)");
  printf("\n");
@


4.6.1.1
log
@WCSLIB 4.6 development branch.
@
text
@d31 1
a31 1
  $Id: lin.c,v 4.6 2010/11/16 06:15:31 cal103 Exp $
@


4.6.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2011, Mark Calabretta
d31 1
a31 1
  $Id: lin.c,v 4.6.1.1 2010/11/16 06:16:19 cal103 Exp cal103 $
@


4.6.1.3
log
@Replaced calls to printf() with wcsprintf().
@
text
@d31 1
a31 1
  $Id: lin.c,v 4.6.1.2 2011/01/14 06:33:16 cal103 Exp cal103 $
a36 2

#include "wcsprintf.h"
d284 1
a284 1
    wcsprintf("The linprm struct is UNINITIALIZED.\n");
d288 4
a291 4
  wcsprintf("       flag: %d\n", lin->flag);
  wcsprintf("      naxis: %d\n", lin->naxis);
  wcsprintf("      crpix: %p\n", (void *)lin->crpix);
  wcsprintf("            ");
d293 1
a293 1
    wcsprintf("  %- 11.5g", lin->crpix[i]);
d295 1
a295 1
  wcsprintf("\n");
d298 1
a298 1
  wcsprintf("         pc: %p\n", (void *)lin->pc);
d300 1
a300 1
    wcsprintf("    pc[%d][]:", i);
d302 1
a302 1
      wcsprintf("  %- 11.5g", lin->pc[k++]);
d304 1
a304 1
    wcsprintf("\n");
d307 2
a308 2
  wcsprintf("      cdelt: %p\n", (void *)lin->cdelt);
  wcsprintf("            ");
d310 1
a310 1
    wcsprintf("  %- 11.5g", lin->cdelt[i]);
d312 1
a312 1
  wcsprintf("\n");
d314 1
a314 1
  wcsprintf("      unity: %d\n", lin->unity);
d317 1
a317 1
    wcsprintf("     piximg: (nil)\n");
d321 1
a321 1
      wcsprintf("piximg[%d][]:", i);
d323 1
a323 1
        wcsprintf("  %- 11.5g", lin->piximg[k++]);
d325 1
a325 1
      wcsprintf("\n");
d330 1
a330 1
    wcsprintf("     imgpix: (nil)\n");
d334 1
a334 1
      wcsprintf("imgpix[%d][]:", i);
d336 1
a336 1
        wcsprintf("  %- 11.5g", lin->imgpix[k++]);
d338 1
a338 1
      wcsprintf("\n");
d342 11
a352 11
  wcsprintf("     m_flag: %d\n", lin->m_flag);
  wcsprintf("    m_naxis: %d\n", lin->m_naxis);
  wcsprintf("    m_crpix: %p", (void *)lin->m_crpix);
  if (lin->m_crpix == lin->crpix) wcsprintf("  (= crpix)");
  wcsprintf("\n");
  wcsprintf("       m_pc: %p", (void *)lin->m_pc);
  if (lin->m_pc == lin->pc) wcsprintf("  (= pc)");
  wcsprintf("\n");
  wcsprintf("    m_cdelt: %p", (void *)lin->m_cdelt);
  if (lin->m_cdelt == lin->cdelt) wcsprintf("  (= cdelt)");
  wcsprintf("\n");
@


4.5
log
@WCSLIB 4.5
@
text
@d3 1
a3 1
  WCSLIB 4.5 - an implementation of the FITS WCS standard.
d31 1
a31 1
  $Id: lin.c,v 4.4.1.2 2010/01/19 03:42:50 cal103 Exp cal103 $
@


4.5.1.1
log
@WCSLIB 4.5 development branch.
@
text
@d31 1
a31 1
  $Id: lin.c,v 4.5 2010/07/16 07:01:25 cal103 Exp $
@


4.4
log
@WCSLIB 4.4
@
text
@d3 2
a4 2
  WCSLIB 4.4 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2009, Mark Calabretta
d31 1
a31 1
  $Id: lin.c,v 4.3.1.2 2009/07/22 04:28:39 cal103 Exp cal103 $
@


4.4.1.1
log
@WCSLIB 4.4 development branch.
@
text
@d31 1
a31 1
  $Id: lin.c,v 4.4 2009/08/06 07:41:33 cal103 Exp $
@


4.4.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2010, Mark Calabretta
d31 1
a31 1
  $Id: lin.c,v 4.4.1.1 2009/08/10 08:52:49 cal103 Exp cal103 $
@


4.3
log
@WCSLIB 4.3
@
text
@d3 2
a4 2
    WCSLIB 4.3 - an implementation of the FITS WCS standard.
    Copyright (C) 1995-2007, Mark Calabretta
d6 1
a6 1
    This file is part of WCSLIB.
d8 24
a31 24
    WCSLIB is free software: you can redistribute it and/or modify it under
    the terms of the GNU Lesser General Public License as published by the
    Free Software Foundation, either version 3 of the License, or (at your
    option) any later version.

    WCSLIB is distributed in the hope that it will be useful, but WITHOUT ANY
    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
    more details.

    You should have received a copy of the GNU Lesser General Public License
    along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.

    Correspondence concerning WCSLIB may be directed to:
       Internet email: mcalabre@@atnf.csiro.au
       Postal address: Dr. Mark Calabretta
                       Australia Telescope National Facility, CSIRO
                       PO Box 76
                       Epping NSW 1710
                       AUSTRALIA

    Author: Mark Calabretta, Australia Telescope National Facility
    http://www.atnf.csiro.au/~mcalabre/index.html
    $Id: lin.c,v 4.2.1.6 2007/12/03 05:02:17 cal103 Exp cal103 $
d45 2
a46 2
   "Memory allocation failed",
   "PCi_ja matrix is singular"};
d57 2
a58 93
   int i, j;
   double *pc;

   if (lin == 0x0) return 1;
   if (naxis <= 0) {
      return 2;
   }

   if (lin->flag == -1 || lin->m_flag != LINSET) {
      lin->m_flag  = 0;
      lin->m_naxis = 0x0;
      lin->m_crpix = 0x0;
      lin->m_pc    = 0x0;
      lin->m_cdelt = 0x0;
   }


   /* Allocate memory for arrays if required. */
   if (alloc ||
       lin->crpix == 0x0 ||
       lin->pc    == 0x0 ||
       lin->cdelt == 0x0) {

      /* Was sufficient allocated previously? */
      if (lin->m_flag == LINSET && lin->m_naxis < naxis) {
         /* No, free it. */
         linfree(lin);
      }

      if (alloc || lin->crpix == 0x0) {
         if (lin->m_crpix) {
            /* In case the caller fiddled with it. */
            lin->crpix = lin->m_crpix;

         } else {
            if (!(lin->crpix = calloc(naxis, sizeof(double)))) {
               return 2;
            }

            lin->m_flag  = LINSET;
            lin->m_naxis = naxis;
            lin->m_crpix = lin->crpix;
         }
      }

      if (alloc || lin->pc == 0x0) {
         if (lin->m_pc) {
            /* In case the caller fiddled with it. */
            lin->pc = lin->m_pc;

         } else {
            if (!(lin->pc = calloc(naxis*naxis, sizeof(double)))) {
               linfree(lin);
               return 2;
            }

            lin->m_flag  = LINSET;
            lin->m_naxis = naxis;
            lin->m_pc    = lin->pc;
         }
      }

      if (alloc || lin->cdelt == 0x0) {
         if (lin->m_cdelt) {
            /* In case the caller fiddled with it. */
            lin->cdelt = lin->m_cdelt;

         } else {
            if (!(lin->cdelt = calloc(naxis, sizeof(double)))) {
               linfree(lin);
               return 2;
            }

            lin->m_flag  = LINSET;
            lin->m_naxis = naxis;
            lin->m_cdelt = lin->cdelt;
         }
      }
   }

   /* Free memory allocated by linset(). */
   if (lin->flag == LINSET) {
      if (lin->piximg) free(lin->piximg);
      if (lin->imgpix) free(lin->imgpix);
   }

   lin->piximg = 0x0;
   lin->imgpix = 0x0;
   lin->i_naxis = 0x0;


   lin->flag  = 0;
   lin->naxis = naxis;
d60 116
a176 24
   /* CRPIXja defaults to 0.0. */
   for (j = 0; j < naxis; j++) {
      lin->crpix[j] = 0.0;
   }


   /* PCi_ja defaults to the unit matrix. */
   pc = lin->pc;
   for (i = 0; i < naxis; i++) {
      for (j = 0; j < naxis; j++) {
         if (j == i) {
            *pc = 1.0;
         } else {
            *pc = 0.0;
         }
         pc++;
      }
   }


   /* CDELTia defaults to 1.0. */
   for (i = 0; i < naxis; i++) {
      lin->cdelt[i] = 1.0;
   }
d178 1
a178 2

   return 0;
d190 25
a214 18
   int i, j, naxis, status;
   const double *srcp;
   double *dstp;

   if (linsrc == 0x0) return 1;

   naxis = linsrc->naxis;
   if (naxis <= 0) {
      return 2;
   }

   if ((status = linini(alloc, naxis, lindst))) {
      return status;
   }

   srcp = linsrc->crpix;
   dstp = lindst->crpix;
   for (j = 0; j < naxis; j++) {
d216 2
a217 9
   }

   srcp = linsrc->pc;
   dstp = lindst->pc;
   for (i = 0; i < naxis; i++) {
      for (j = 0; j < naxis; j++) {
         *(dstp++) = *(srcp++);
      }
   }
d219 5
a223 5
   srcp = linsrc->cdelt;
   dstp = lindst->cdelt;
   for (i = 0; i < naxis; i++) {
      *(dstp++) = *(srcp++);
   }
d225 1
a225 1
   return 0;
d235 1
a235 27
   if (lin == 0x0) return 1;

   if (lin->flag != -1) {
      /* Free memory allocated by linini(). */
      if (lin->m_flag == LINSET) {
         if (lin->crpix == lin->m_crpix) lin->crpix = 0x0;
         if (lin->pc    == lin->m_pc)    lin->pc    = 0x0;
         if (lin->cdelt == lin->m_cdelt) lin->cdelt = 0x0;

         if (lin->m_crpix) free(lin->m_crpix);
         if (lin->m_pc)    free(lin->m_pc);
         if (lin->m_cdelt) free(lin->m_cdelt);
      }
   }

   lin->m_flag  = 0;
   lin->m_naxis = 0;
   lin->m_crpix = 0x0;
   lin->m_pc    = 0x0;
   lin->m_cdelt = 0x0;


   /* Free memory allocated by linset(). */
   if (lin->flag == LINSET) {
      if (lin->piximg) free(lin->piximg);
      if (lin->imgpix) free(lin->imgpix);
   }
d237 29
a265 3
   lin->piximg = 0x0;
   lin->imgpix = 0x0;
   lin->i_naxis = 0;
d267 1
a267 1
   lin->flag = 0;
d269 1
a269 1
   return 0;
d279 1
a279 8
   int i, j, k;

   if (lin == 0x0) return 1;

   if (lin->flag != LINSET) {
      printf("The linprm struct is UNINITIALIZED.\n");
      return 0;
   }
d281 1
a281 8
   printf("       flag: %d\n", lin->flag);
   printf("      naxis: %d\n", lin->naxis);
   printf("      crpix: %p\n", (void *)lin->crpix);
   printf("            ");
   for (i = 0; i < lin->naxis; i++) {
      printf("  %- 11.5g", lin->crpix[i]);
   }
   printf("\n");
d283 39
a321 4
   k = 0;
   printf("         pc: %p\n", (void *)lin->pc);
   for (i = 0; i < lin->naxis; i++) {
      printf("    pc[%d][]:", i);
d323 1
a323 1
         printf("  %- 11.5g", lin->pc[k++]);
d326 2
a327 1
   }
d329 8
a336 19
   printf("      cdelt: %p\n", (void *)lin->cdelt);
   printf("            ");
   for (i = 0; i < lin->naxis; i++) {
      printf("  %- 11.5g", lin->cdelt[i]);
   }
   printf("\n");

   printf("      unity: %d\n", lin->unity);

   if (lin->piximg == 0x0) {
      printf("     piximg: (nil)\n");
   } else {
      k = 0;
      for (i = 0; i < lin->naxis; i++) {
         printf("piximg[%d][]:", i);
         for (j = 0; j < lin->naxis; j++) {
            printf("  %- 11.5g", lin->piximg[k++]);
         }
         printf("\n");
d338 3
a340 1
   }
d342 11
a352 12
   if (lin->imgpix == 0x0) {
      printf("     imgpix: (nil)\n");
   } else {
      k = 0;
      for (i = 0; i < lin->naxis; i++) {
         printf("imgpix[%d][]:", i);
         for (j = 0; j < lin->naxis; j++) {
            printf("  %- 11.5g", lin->imgpix[k++]);
         }
         printf("\n");
      }
   }
d354 1
a354 13
   printf("     m_flag: %d\n", lin->m_flag);
   printf("    m_naxis: %d\n", lin->m_naxis);
   printf("    m_crpix: %p", (void *)lin->m_crpix);
   if (lin->m_crpix == lin->crpix) printf("  (= crpix)");
   printf("\n");
   printf("       m_pc: %p", (void *)lin->m_pc);
   if (lin->m_pc == lin->pc) printf("  (= pc)");
   printf("\n");
   printf("    m_cdelt: %p", (void *)lin->m_cdelt);
   if (lin->m_cdelt == lin->cdelt) printf("  (= cdelt)");
   printf("\n");

   return 0;
d364 6
a369 2
   int i, j, n, status;
   double *pc, *piximg;
d371 26
a396 1
   if (lin == 0x0) return 1;
d398 3
a400 1
   n = lin->naxis;
d402 6
a407 16
   /* Check for a unit matrix. */
   lin->unity = 1;
   pc = lin->pc;
   for (i = 0; i < n; i++) {
      for (j = 0; j < n; j++) {
         if (j == i) {
            if (*(pc++) != 1.0) {
               lin->unity = 0;
               break;
            }
         } else {
            if (*(pc++) != 0.0) {
               lin->unity = 0;
               break;
            }
         }
a408 1
   }
d410 4
d415 3
a417 39
   if (lin->unity) {
      if (lin->flag == LINSET) {
         /* Free memory that may have been allocated previously. */
         if (lin->piximg) free(lin->piximg);
         if (lin->imgpix) free(lin->imgpix);
      }

      lin->piximg = 0x0;
      lin->imgpix = 0x0;
      lin->i_naxis = 0;

   } else {
      if (lin->flag != LINSET || lin->i_naxis < n) {
         if (lin->flag == LINSET) {
            /* Free memory that may have been allocated previously. */
            if (lin->piximg) free(lin->piximg);
            if (lin->imgpix) free(lin->imgpix);
         }

         /* Allocate memory for internal arrays. */
         if (!(lin->piximg = calloc(n*n, sizeof(double)))) {
            return 2;
         }

         if (!(lin->imgpix = calloc(n*n, sizeof(double)))) {
            free(lin->piximg);
            return 2;
         }

         lin->i_naxis = n;
      }

      /* Compute the pixel-to-image transformation matrix. */
      pc     = lin->pc;
      piximg = lin->piximg;
      for (i = 0; i < n; i++) {
         for (j = 0; j < n; j++) {
            *(piximg++) = lin->cdelt[i] * (*(pc++));
         }
d420 9
a428 3
      /* Compute the image-to-pixel transformation matrix. */
      if ((status = matinv(n, lin->piximg, lin->imgpix))) {
         return status;
d430 7
a436 1
   }
d439 1
a439 1
   lin->flag = LINSET;
d441 1
a441 1
   return 0;
d454 4
a457 5
   int i, j, k, n, status;
   double temp;
   register const double *pix;
   register double *img, *piximg;

a458 5
   /* Initialize. */
   if (lin == 0x0) return 1;
   if (lin->flag != LINSET) {
      if ((status = linset(lin))) return status;
   }
d460 5
a464 1
   n = lin->naxis;
d466 1
a467 3
   /* Convert pixel coordinates to intermediate world coordinates. */
   pix = pixcrd;
   img = imgcrd;
d469 3
a471 5
   if (lin->unity) {
      for (k = 0; k < ncoord; k++) {
         for (i = 0; i < n; i++) {
            *(img++) = lin->cdelt[i] * (*(pix++) - lin->crpix[i]);
         }
d473 4
a476 2
         pix += (nelem - n);
         img += (nelem - n);
d479 3
a481 5
   } else {
      for (k = 0; k < ncoord; k++) {
         for (i = 0; i < n; i++) {
            img[i] = 0.0;
         }
d483 5
a487 3
         for (j = 0; j < n; j++) {
            /* Column-wise multiplication allows this to be cached. */
            temp = *(pix++) - lin->crpix[j];
d489 3
a491 5
            piximg = lin->piximg + j;
            for (i = 0; i < n; i++, piximg += n) {
               img[i] += *piximg * temp;
            }
         }
d493 4
a496 2
         pix += (nelem - n);
         img += nelem;
a497 1
   }
d499 6
a504 1
   return 0;
d517 3
a519 3
   int i, j, k, n, status;
   register const double *img;
   register double *imgpix, *pix;
d522 5
a526 5
   /* Initialize. */
   if (lin == 0x0) return 1;
   if (lin->flag != LINSET) {
      if ((status = linset(lin))) return status;
   }
d528 1
a528 1
   n = lin->naxis;
d531 3
a533 3
   /* Convert intermediate world coordinates to pixel coordinates. */
   img = imgcrd;
   pix = pixcrd;
d535 4
a538 8
   if (lin->unity) {
      for (k = 0; k < ncoord; k++) {
         for (j = 0; j < n; j++) {
            *(pix++) = (*(img++) / lin->cdelt[j]) + lin->crpix[j];
         }

         pix += (nelem - n);
         img += (nelem - n);
d541 3
a543 3
   } else {
      for (k = 0; k < ncoord; k++) {
         imgpix = lin->imgpix;
d545 3
a547 6
         for (j = 0; j < n; j++) {
            *pix = 0.0;
            for (i = 0; i < n; i++) {
               *pix += *imgpix * img[i];
               imgpix++;
            }
d549 6
a554 2
            *(pix++) += lin->crpix[j];
         }
d556 1
a556 2
         pix += (nelem - n);
         img += nelem;
a557 1
   }
d559 6
a564 1
   return 0;
d576 36
a611 3
   register int i, ij, ik, j, k, kj, pj;
   int    itemp, *mxl, *lxm, pivot;
   double colmax, *lu, *rowmax, dtemp;
d613 2
d616 2
a617 14
   /* Allocate memory for internal arrays. */
   if (!(mxl = calloc(n, sizeof(int)))) return 2;
   if (!(lxm = calloc(n, sizeof(int)))) {
      free(mxl);
      return 2;
   }

   if (!(rowmax = calloc(n, sizeof(double)))) {
      free(mxl);
      free(lxm);
      return 2;
   }

   if (!(lu = calloc(n*n, sizeof(double)))) {
d621 86
a706 111
      return 2;
   }


   /* Initialize arrays. */
   for (i = 0, ij = 0; i < n; i++) {
      /* Vector that records row interchanges. */
      mxl[i] = i;

      rowmax[i] = 0.0;

      for (j = 0; j < n; j++, ij++) {
         dtemp = fabs(mat[ij]);
         if (dtemp > rowmax[i]) rowmax[i] = dtemp;

         lu[ij] = mat[ij];
      }

      /* A row of zeroes indicates a singular matrix. */
      if (rowmax[i] == 0.0) {
         free(mxl);
         free(lxm);
         free(rowmax);
         free(lu);
         return 3;
      }
   }


   /* Form the LU triangular factorization using scaled partial pivoting. */
   for (k = 0; k < n; k++) {
      /* Decide whether to pivot. */
      colmax = fabs(lu[k*n+k]) / rowmax[k];
      pivot = k;

      for (i = k+1; i < n; i++) {
         ik = i*n + k;
         dtemp = fabs(lu[ik]) / rowmax[i];
         if (dtemp > colmax) {
            colmax = dtemp;
            pivot = i;
         }
      }

      if (pivot > k) {
         /* We must pivot, interchange the rows of the design matrix. */
         for (j = 0, pj = pivot*n, kj = k*n; j < n; j++, pj++, kj++) {
            dtemp = lu[pj];
            lu[pj] = lu[kj];
            lu[kj] = dtemp;
         }

         /* Amend the vector of row maxima. */
         dtemp = rowmax[pivot];
         rowmax[pivot] = rowmax[k];
         rowmax[k] = dtemp;

         /* Record the interchange for later use. */
         itemp = mxl[pivot];
         mxl[pivot] = mxl[k];
         mxl[k] = itemp;
      }

      /* Gaussian elimination. */
      for (i = k+1; i < n; i++) {
         ik = i*n + k;

         /* Nothing to do if lu[ik] is zero. */
         if (lu[ik] != 0.0) {
            /* Save the scaling factor. */
            lu[ik] /= lu[k*n+k];

            /* Subtract rows. */
            for (j = k+1; j < n; j++) {
               lu[i*n+j] -= lu[ik]*lu[k*n+j];
            }
         }
      }
   }


   /* mxl[i] records which row of mat corresponds to row i of lu.  */
   /* lxm[i] records which row of lu  corresponds to row i of mat. */
   for (i = 0; i < n; i++) {
      lxm[mxl[i]] = i;
   }


   /* Determine the inverse matrix. */
   for (i = 0, ij = 0; i < n; i++) {
      for (j = 0; j < n; j++, ij++) {
         inv[ij] = 0.0;
      }
   }

   for (k = 0; k < n; k++) {
      inv[lxm[k]*n+k] = 1.0;

      /* Forward substitution. */
      for (i = lxm[k]+1; i < n; i++) {
         for (j = lxm[k]; j < i; j++) {
            inv[i*n+k] -= lu[i*n+j]*inv[j*n+k];
         }
      }

      /* Backward substitution. */
      for (i = n-1; i >= 0; i--) {
         for (j = i+1; j < n; j++) {
            inv[i*n+k] -= lu[i*n+j]*inv[j*n+k];
         }
         inv[i*n+k] /= lu[i*n+i];
d708 2
@


4.3.1.1
log
@WCSLIB 4.3 development branch.
@
text
@d3 2
a4 2
    WCSLIB 4.4 - an implementation of the FITS WCS standard.
    Copyright (C) 1995-2008, Mark Calabretta
d31 1
a31 1
    $Id: lin.c,v 4.3 2007/12/27 05:41:36 cal103 Exp cal103 $
@


4.3.1.2
log
@Changed indentation.
@
text
@d3 2
a4 2
  WCSLIB 4.4 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2009, Mark Calabretta
d6 1
a6 1
  This file is part of WCSLIB.
d8 24
a31 24
  WCSLIB is free software: you can redistribute it and/or modify it under the
  terms of the GNU Lesser General Public License as published by the Free
  Software Foundation, either version 3 of the License, or (at your option)
  any later version.

  WCSLIB is distributed in the hope that it will be useful, but WITHOUT ANY
  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
  more details.

  You should have received a copy of the GNU Lesser General Public License
  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.

  Correspondence concerning WCSLIB may be directed to:
    Internet email: mcalabre@@atnf.csiro.au
    Postal address: Dr. Mark Calabretta
                    Australia Telescope National Facility, CSIRO
                    PO Box 76
                    Epping NSW 1710
                    AUSTRALIA

  Author: Mark Calabretta, Australia Telescope National Facility
  http://www.atnf.csiro.au/~mcalabre/index.html
  $Id: lin.c,v 4.3.1.1 2007/12/27 13:23:47 cal103 Exp cal103 $
d45 2
a46 2
  "Memory allocation failed",
  "PCi_ja matrix is singular"};
d57 93
a149 2
  int i, j;
  double *pc;
a150 116
  if (lin == 0x0) return 1;
  if (naxis <= 0) {
    return 2;
  }

  if (lin->flag == -1 || lin->m_flag != LINSET) {
    lin->m_flag  = 0;
    lin->m_naxis = 0x0;
    lin->m_crpix = 0x0;
    lin->m_pc    = 0x0;
    lin->m_cdelt = 0x0;
  }


  /* Allocate memory for arrays if required. */
  if (alloc ||
     lin->crpix == 0x0 ||
     lin->pc    == 0x0 ||
     lin->cdelt == 0x0) {

    /* Was sufficient allocated previously? */
    if (lin->m_flag == LINSET && lin->m_naxis < naxis) {
      /* No, free it. */
      linfree(lin);
    }

    if (alloc || lin->crpix == 0x0) {
      if (lin->m_crpix) {
        /* In case the caller fiddled with it. */
        lin->crpix = lin->m_crpix;

      } else {
        if (!(lin->crpix = calloc(naxis, sizeof(double)))) {
          return 2;
        }

        lin->m_flag  = LINSET;
        lin->m_naxis = naxis;
        lin->m_crpix = lin->crpix;
      }
    }

    if (alloc || lin->pc == 0x0) {
      if (lin->m_pc) {
        /* In case the caller fiddled with it. */
        lin->pc = lin->m_pc;

      } else {
        if (!(lin->pc = calloc(naxis*naxis, sizeof(double)))) {
          linfree(lin);
          return 2;
        }

        lin->m_flag  = LINSET;
        lin->m_naxis = naxis;
        lin->m_pc    = lin->pc;
      }
    }

    if (alloc || lin->cdelt == 0x0) {
      if (lin->m_cdelt) {
        /* In case the caller fiddled with it. */
        lin->cdelt = lin->m_cdelt;

      } else {
        if (!(lin->cdelt = calloc(naxis, sizeof(double)))) {
          linfree(lin);
          return 2;
        }

        lin->m_flag  = LINSET;
        lin->m_naxis = naxis;
        lin->m_cdelt = lin->cdelt;
      }
    }
  }

  /* Free memory allocated by linset(). */
  if (lin->flag == LINSET) {
    if (lin->piximg) free(lin->piximg);
    if (lin->imgpix) free(lin->imgpix);
  }

  lin->piximg = 0x0;
  lin->imgpix = 0x0;
  lin->i_naxis = 0x0;


  lin->flag  = 0;
  lin->naxis = naxis;


  /* CRPIXja defaults to 0.0. */
  for (j = 0; j < naxis; j++) {
    lin->crpix[j] = 0.0;
  }


  /* PCi_ja defaults to the unit matrix. */
  pc = lin->pc;
  for (i = 0; i < naxis; i++) {
    for (j = 0; j < naxis; j++) {
      if (j == i) {
        *pc = 1.0;
      } else {
        *pc = 0.0;
      }
      pc++;
    }
  }


  /* CDELTia defaults to 1.0. */
  for (i = 0; i < naxis; i++) {
    lin->cdelt[i] = 1.0;
  }
d152 24
d177 2
a178 1
  return 0;
d190 18
a207 25
  int i, j, naxis, status;
  const double *srcp;
  double *dstp;

  if (linsrc == 0x0) return 1;

  naxis = linsrc->naxis;
  if (naxis <= 0) {
    return 2;
  }

  if ((status = linini(alloc, naxis, lindst))) {
    return status;
  }

  srcp = linsrc->crpix;
  dstp = lindst->crpix;
  for (j = 0; j < naxis; j++) {
    *(dstp++) = *(srcp++);
  }

  srcp = linsrc->pc;
  dstp = lindst->pc;
  for (i = 0; i < naxis; i++) {
    for (j = 0; j < naxis; j++) {
d209 9
a217 2
    }
  }
d219 5
a223 5
  srcp = linsrc->cdelt;
  dstp = lindst->cdelt;
  for (i = 0; i < naxis; i++) {
    *(dstp++) = *(srcp++);
  }
d225 1
a225 1
  return 0;
d235 27
a261 1
  if (lin == 0x0) return 1;
d263 3
a265 29
  if (lin->flag != -1) {
    /* Free memory allocated by linini(). */
    if (lin->m_flag == LINSET) {
      if (lin->crpix == lin->m_crpix) lin->crpix = 0x0;
      if (lin->pc    == lin->m_pc)    lin->pc    = 0x0;
      if (lin->cdelt == lin->m_cdelt) lin->cdelt = 0x0;

      if (lin->m_crpix) free(lin->m_crpix);
      if (lin->m_pc)    free(lin->m_pc);
      if (lin->m_cdelt) free(lin->m_cdelt);
    }
  }

  lin->m_flag  = 0;
  lin->m_naxis = 0;
  lin->m_crpix = 0x0;
  lin->m_pc    = 0x0;
  lin->m_cdelt = 0x0;


  /* Free memory allocated by linset(). */
  if (lin->flag == LINSET) {
    if (lin->piximg) free(lin->piximg);
    if (lin->imgpix) free(lin->imgpix);
  }

  lin->piximg = 0x0;
  lin->imgpix = 0x0;
  lin->i_naxis = 0;
d267 1
a267 1
  lin->flag = 0;
d269 1
a269 1
  return 0;
d279 8
a286 1
  int i, j, k;
d288 8
a295 1
  if (lin == 0x0) return 1;
d297 4
a300 39
  if (lin->flag != LINSET) {
    printf("The linprm struct is UNINITIALIZED.\n");
    return 0;
  }

  printf("       flag: %d\n", lin->flag);
  printf("      naxis: %d\n", lin->naxis);
  printf("      crpix: %p\n", (void *)lin->crpix);
  printf("            ");
  for (i = 0; i < lin->naxis; i++) {
    printf("  %- 11.5g", lin->crpix[i]);
  }
  printf("\n");

  k = 0;
  printf("         pc: %p\n", (void *)lin->pc);
  for (i = 0; i < lin->naxis; i++) {
    printf("    pc[%d][]:", i);
    for (j = 0; j < lin->naxis; j++) {
      printf("  %- 11.5g", lin->pc[k++]);
    }
    printf("\n");
  }

  printf("      cdelt: %p\n", (void *)lin->cdelt);
  printf("            ");
  for (i = 0; i < lin->naxis; i++) {
    printf("  %- 11.5g", lin->cdelt[i]);
  }
  printf("\n");

  printf("      unity: %d\n", lin->unity);

  if (lin->piximg == 0x0) {
    printf("     piximg: (nil)\n");
  } else {
    k = 0;
    for (i = 0; i < lin->naxis; i++) {
      printf("piximg[%d][]:", i);
d302 1
a302 1
        printf("  %- 11.5g", lin->piximg[k++]);
d305 1
a305 2
    }
  }
d307 32
a338 8
  if (lin->imgpix == 0x0) {
    printf("     imgpix: (nil)\n");
  } else {
    k = 0;
    for (i = 0; i < lin->naxis; i++) {
      printf("imgpix[%d][]:", i);
      for (j = 0; j < lin->naxis; j++) {
        printf("  %- 11.5g", lin->imgpix[k++]);
d340 1
a340 3
      printf("\n");
    }
  }
d342 11
a352 11
  printf("     m_flag: %d\n", lin->m_flag);
  printf("    m_naxis: %d\n", lin->m_naxis);
  printf("    m_crpix: %p", (void *)lin->m_crpix);
  if (lin->m_crpix == lin->crpix) printf("  (= crpix)");
  printf("\n");
  printf("       m_pc: %p", (void *)lin->m_pc);
  if (lin->m_pc == lin->pc) printf("  (= pc)");
  printf("\n");
  printf("    m_cdelt: %p", (void *)lin->m_cdelt);
  if (lin->m_cdelt == lin->cdelt) printf("  (= cdelt)");
  printf("\n");
d354 1
a354 1
  return 0;
d364 2
a365 2
  int i, j, n, status;
  double *pc, *piximg;
d367 1
a367 1
  if (lin == 0x0) return 1;
d369 1
a369 1
  n = lin->naxis;
d371 18
a388 26
  /* Check for a unit matrix. */
  lin->unity = 1;
  pc = lin->pc;
  for (i = 0; i < n; i++) {
    for (j = 0; j < n; j++) {
      if (j == i) {
        if (*(pc++) != 1.0) {
          lin->unity = 0;
          break;
        }
      } else {
        if (*(pc++) != 0.0) {
          lin->unity = 0;
          break;
        }
      }
    }
  }


  if (lin->unity) {
    if (lin->flag == LINSET) {
      /* Free memory that may have been allocated previously. */
      if (lin->piximg) free(lin->piximg);
      if (lin->imgpix) free(lin->imgpix);
    }
a389 3
    lin->piximg = 0x0;
    lin->imgpix = 0x0;
    lin->i_naxis = 0;
d391 1
a391 2
  } else {
    if (lin->flag != LINSET || lin->i_naxis < n) {
d393 37
a429 3
        /* Free memory that may have been allocated previously. */
        if (lin->piximg) free(lin->piximg);
        if (lin->imgpix) free(lin->imgpix);
d432 3
a434 3
      /* Allocate memory for internal arrays. */
      if (!(lin->piximg = calloc(n*n, sizeof(double)))) {
        return 2;
d436 1
a437 4
      if (!(lin->imgpix = calloc(n*n, sizeof(double)))) {
        free(lin->piximg);
        return 2;
      }
d439 1
a439 2
      lin->i_naxis = n;
    }
d441 1
a441 19
    /* Compute the pixel-to-image transformation matrix. */
    pc     = lin->pc;
    piximg = lin->piximg;
    for (i = 0; i < n; i++) {
      for (j = 0; j < n; j++) {
        *(piximg++) = lin->cdelt[i] * (*(pc++));
      }
    }

    /* Compute the image-to-pixel transformation matrix. */
    if ((status = matinv(n, lin->piximg, lin->imgpix))) {
      return status;
    }
  }


  lin->flag = LINSET;

  return 0;
d454 5
a458 4
  int i, j, k, n, status;
  double temp;
  register const double *pix;
  register double *img, *piximg;
d460 5
d466 1
a466 5
  /* Initialize. */
  if (lin == 0x0) return 1;
  if (lin->flag != LINSET) {
    if ((status = linset(lin))) return status;
  }
a467 1
  n = lin->naxis;
d469 3
d473 5
a477 3
  /* Convert pixel coordinates to intermediate world coordinates. */
  pix = pixcrd;
  img = imgcrd;
d479 2
a480 4
  if (lin->unity) {
    for (k = 0; k < ncoord; k++) {
      for (i = 0; i < n; i++) {
        *(img++) = lin->cdelt[i] * (*(pix++) - lin->crpix[i]);
d483 5
a487 3
      pix += (nelem - n);
      img += (nelem - n);
    }
d489 3
a491 5
  } else {
    for (k = 0; k < ncoord; k++) {
      for (i = 0; i < n; i++) {
        img[i] = 0.0;
      }
d493 5
a497 3
      for (j = 0; j < n; j++) {
        /* Column-wise multiplication allows this to be cached. */
        temp = *(pix++) - lin->crpix[j];
d499 2
a500 4
        piximg = lin->piximg + j;
        for (i = 0; i < n; i++, piximg += n) {
          img[i] += *piximg * temp;
        }
d502 1
d504 1
a504 6
      pix += (nelem - n);
      img += nelem;
    }
  }

  return 0;
d517 3
a519 3
  int i, j, k, n, status;
  register const double *img;
  register double *imgpix, *pix;
d522 7
a528 5
  /* Initialize. */
  if (lin == 0x0) return 1;
  if (lin->flag != LINSET) {
    if ((status = linset(lin))) return status;
  }
a529 1
  n = lin->naxis;
d531 3
d535 5
a539 3
  /* Convert intermediate world coordinates to pixel coordinates. */
  img = imgcrd;
  pix = pixcrd;
d541 2
a542 4
  if (lin->unity) {
    for (k = 0; k < ncoord; k++) {
      for (j = 0; j < n; j++) {
        *(pix++) = (*(img++) / lin->cdelt[j]) + lin->crpix[j];
d545 3
a547 3
      pix += (nelem - n);
      img += (nelem - n);
    }
d549 6
a554 3
  } else {
    for (k = 0; k < ncoord; k++) {
      imgpix = lin->imgpix;
d556 2
a557 6
      for (j = 0; j < n; j++) {
        *pix = 0.0;
        for (i = 0; i < n; i++) {
          *pix += *imgpix * img[i];
          imgpix++;
        }
d559 2
a560 1
        *(pix++) += lin->crpix[j];
d562 1
d564 1
a564 6
      pix += (nelem - n);
      img += nelem;
    }
  }

  return 0;
d576 3
a578 36
  register int i, ij, ik, j, k, kj, pj;
  int    itemp, *mxl, *lxm, pivot;
  double colmax, *lu, *rowmax, dtemp;


  /* Allocate memory for internal arrays. */
  if (!(mxl = calloc(n, sizeof(int)))) return 2;
  if (!(lxm = calloc(n, sizeof(int)))) {
    free(mxl);
    return 2;
  }

  if (!(rowmax = calloc(n, sizeof(double)))) {
    free(mxl);
    free(lxm);
    return 2;
  }

  if (!(lu = calloc(n*n, sizeof(double)))) {
    free(mxl);
    free(lxm);
    free(rowmax);
    return 2;
  }


  /* Initialize arrays. */
  for (i = 0, ij = 0; i < n; i++) {
    /* Vector that records row interchanges. */
    mxl[i] = i;

    rowmax[i] = 0.0;

    for (j = 0; j < n; j++, ij++) {
      dtemp = fabs(mat[ij]);
      if (dtemp > rowmax[i]) rowmax[i] = dtemp;
a579 2
      lu[ij] = mat[ij];
    }
d581 14
a594 2
    /* A row of zeroes indicates a singular matrix. */
    if (rowmax[i] == 0.0) {
d598 111
a708 86
      free(lu);
      return 3;
    }
  }


  /* Form the LU triangular factorization using scaled partial pivoting. */
  for (k = 0; k < n; k++) {
    /* Decide whether to pivot. */
    colmax = fabs(lu[k*n+k]) / rowmax[k];
    pivot = k;

    for (i = k+1; i < n; i++) {
      ik = i*n + k;
      dtemp = fabs(lu[ik]) / rowmax[i];
      if (dtemp > colmax) {
        colmax = dtemp;
        pivot = i;
      }
    }

    if (pivot > k) {
      /* We must pivot, interchange the rows of the design matrix. */
      for (j = 0, pj = pivot*n, kj = k*n; j < n; j++, pj++, kj++) {
        dtemp = lu[pj];
        lu[pj] = lu[kj];
        lu[kj] = dtemp;
      }

      /* Amend the vector of row maxima. */
      dtemp = rowmax[pivot];
      rowmax[pivot] = rowmax[k];
      rowmax[k] = dtemp;

      /* Record the interchange for later use. */
      itemp = mxl[pivot];
      mxl[pivot] = mxl[k];
      mxl[k] = itemp;
    }

    /* Gaussian elimination. */
    for (i = k+1; i < n; i++) {
      ik = i*n + k;

      /* Nothing to do if lu[ik] is zero. */
      if (lu[ik] != 0.0) {
        /* Save the scaling factor. */
        lu[ik] /= lu[k*n+k];

        /* Subtract rows. */
        for (j = k+1; j < n; j++) {
          lu[i*n+j] -= lu[ik]*lu[k*n+j];
        }
      }
    }
  }


  /* mxl[i] records which row of mat corresponds to row i of lu.  */
  /* lxm[i] records which row of lu  corresponds to row i of mat. */
  for (i = 0; i < n; i++) {
    lxm[mxl[i]] = i;
  }


  /* Determine the inverse matrix. */
  for (i = 0, ij = 0; i < n; i++) {
    for (j = 0; j < n; j++, ij++) {
      inv[ij] = 0.0;
    }
  }

  for (k = 0; k < n; k++) {
    inv[lxm[k]*n+k] = 1.0;

    /* Forward substitution. */
    for (i = lxm[k]+1; i < n; i++) {
      for (j = lxm[k]; j < i; j++) {
        inv[i*n+k] -= lu[i*n+j]*inv[j*n+k];
      }
    }

    /* Backward substitution. */
    for (i = n-1; i >= 0; i--) {
      for (j = i+1; j < n; j++) {
        inv[i*n+k] -= lu[i*n+j]*inv[j*n+k];
a709 2
      inv[i*n+k] /= lu[i*n+i];
    }
@


4.2
log
@WCSLIB 4.2
@
text
@d2 30
a31 29
*
*   WCSLIB 4.2 - an implementation of the FITS WCS standard.
*   Copyright (C) 1995-2005, Mark Calabretta
*
*   WCSLIB is free software; you can redistribute it and/or modify it under
*   the terms of the GNU General Public License as published by the Free
*   Software Foundation; either version 2 of the License, or (at your option)
*   any later version.
*
*   WCSLIB is distributed in the hope that it will be useful, but WITHOUT ANY
*   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
*   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
*   details.
*
*   You should have received a copy of the GNU General Public License along
*   with WCSLIB; if not, write to the Free Software Foundation, Inc.,
*   59 Temple Place, Suite 330, Boston, MA  02111-1307, USA
*
*   Correspondence concerning WCSLIB may be directed to:
*      Internet email: mcalabre@@atnf.csiro.au
*      Postal address: Dr. Mark Calabretta
*                      Australia Telescope National Facility, CSIRO
*                      PO Box 76
*                      Epping NSW 1710
*                      AUSTRALIA
*
*   Author: Mark Calabretta, Australia Telescope National Facility
*   http://www.atnf.csiro.au/~mcalabre/index.html
*   $Id: lin.c,v 4.1 2005/08/25 07:44:52 cal103 Exp cal103 $
d201 1
a201 1
   if (status = linini(alloc, naxis, lindst)) {
d290 1
a290 1
   printf("      crpix: 0x%x\n", (int)lin->crpix);
d298 1
a298 1
   printf("         pc: 0x%x\n", (int)lin->pc);
d307 1
a307 1
   printf("      cdelt: 0x%x\n", (int)lin->cdelt);
d317 1
a317 1
      printf("     piximg: (null)\n");
d330 1
a330 1
      printf("     imgpix: (null)\n");
d344 1
a344 1
   printf("    m_crpix: 0x%x", (int)lin->m_crpix);
d347 1
a347 1
   printf("       m_pc: 0x%x", (int)lin->m_pc);
d350 1
a350 1
   printf("    m_cdelt: 0x%x", (int)lin->m_cdelt);
d433 1
a433 1
      if (status = matinv(n, lin->piximg, lin->imgpix)) {
d463 1
a463 1
      if (status = linset(lin)) return status;
d525 1
a525 1
      if (status = linset(lin)) return status;
@


4.2.1.1
log
@WCSLIB 4.2 development branch.
@
text
@d3 1
a3 1
*   WCSLIB 4.3 - an implementation of the FITS WCS standard.
d30 1
a30 1
*   $Id: lin.c,v 4.2 2005/09/21 13:21:57 cal103 Exp cal103 $
@


4.2.1.2
log
@In linprt(), use the "%p" printf conversion specifier to print addresses
rather than casting the pointer to int and using "#x".  The latter does not
work on 64-bit machines where sizeof(int) != sizeof(void*).
@
text
@d4 1
a4 1
*   Copyright (C) 1995-2006, Mark Calabretta
d30 1
a30 1
*   $Id: lin.c,v 4.2.1.1 2005/12/05 02:39:43 cal103 Exp cal103 $
d289 1
a289 1
   printf("      crpix: %p\n", lin->crpix);
d297 1
a297 1
   printf("         pc: %p\n", lin->pc);
d306 1
a306 1
   printf("      cdelt: %p\n", lin->cdelt);
d343 1
a343 1
   printf("    m_crpix: %p", lin->m_crpix);
d346 1
a346 1
   printf("       m_pc: %p", lin->m_pc);
d349 1
a349 1
   printf("    m_cdelt: %p", lin->m_cdelt);
@


4.2.1.3
log
@In linprt(), the "%p" printf conversion specifier prints "(nil)" for a null-
pointer so follow suit.
@
text
@d30 1
a30 1
*   $Id: lin.c,v 4.2.1.2 2006/06/01 07:34:15 cal103 Exp cal103 $
d316 1
a316 1
      printf("     piximg: (nil)\n");
d329 1
a329 1
      printf("     imgpix: (nil)\n");
@


4.2.1.4
log
@Parenthesised assignments used as truth values.
@
text
@d4 1
a4 1
*   Copyright (C) 1995-2007, Mark Calabretta
d30 1
a30 1
*   $Id: lin.c,v 4.2.1.3 2006/06/01 07:47:53 cal103 Exp cal103 $
d200 1
a200 1
   if ((status = linini(alloc, naxis, lindst))) {
d432 1
a432 1
      if ((status = matinv(n, lin->piximg, lin->imgpix))) {
d462 1
a462 1
      if ((status = linset(lin))) return status;
d524 1
a524 1
      if ((status = linset(lin))) return status;
@


4.2.1.5
log
@Cast pointers to (void *) for %p formatting by printf() to avert a compiler
warning.
@
text
@d30 1
a30 1
*   $Id: lin.c,v 4.2.1.4 2007/06/29 00:42:28 cal103 Exp cal103 $
d289 1
a289 1
   printf("      crpix: %p\n", (void *)lin->crpix);
d297 1
a297 1
   printf("         pc: %p\n", (void *)lin->pc);
d306 1
a306 1
   printf("      cdelt: %p\n", (void *)lin->cdelt);
d343 1
a343 1
   printf("    m_crpix: %p", (void *)lin->m_crpix);
d346 1
a346 1
   printf("       m_pc: %p", (void *)lin->m_pc);
d349 1
a349 1
   printf("    m_cdelt: %p", (void *)lin->m_cdelt);
@


4.2.1.6
log
@Switched to LGPL 3.0.
@
text
@d2 29
a30 30

    WCSLIB 4.3 - an implementation of the FITS WCS standard.
    Copyright (C) 1995-2007, Mark Calabretta

    This file is part of WCSLIB.

    WCSLIB is free software: you can redistribute it and/or modify it under
    the terms of the GNU Lesser General Public License as published by the
    Free Software Foundation, either version 3 of the License, or (at your
    option) any later version.

    WCSLIB is distributed in the hope that it will be useful, but WITHOUT ANY
    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
    more details.

    You should have received a copy of the GNU Lesser General Public License
    along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.

    Correspondence concerning WCSLIB may be directed to:
       Internet email: mcalabre@@atnf.csiro.au
       Postal address: Dr. Mark Calabretta
                       Australia Telescope National Facility, CSIRO
                       PO Box 76
                       Epping NSW 1710
                       AUSTRALIA

    Author: Mark Calabretta, Australia Telescope National Facility
    http://www.atnf.csiro.au/~mcalabre/index.html
    $Id: lin.c,v 4.2.1.5 2007/07/11 02:01:30 cal103 Exp cal103 $
@


4.1
log
@WCSLIB 4.1: set lin_errmsg[0] to "success"; report parameters to an extra
decimal place in linprt().
@
text
@d3 1
a3 1
*   WCSLIB 4.1 - an implementation of the FITS WCS standard.
d30 1
a30 1
*   $Id: lin.c,v 4.0 2005/02/04 05:07:48 cal103 Exp cal103 $
@


4.0
log
@WCSLIB 4.0: changed from LGPL to GPL; removed unnecessary casts of void
pointers (a hangover from K&R C).
@
text
@d3 1
a3 1
*   WCSLIB 4.0 - an implementation of the FITS WCS standard.
d30 1
a30 1
*   $Id: lin.c,v 3.6 2004/08/25 04:10:18 cal103 Exp cal103 $
d42 1
a42 1
   0,
d59 1
a59 1
   if (lin == 0) return 1;
d66 4
a69 4
      lin->m_naxis = 0;
      lin->m_crpix = 0;
      lin->m_pc    = 0;
      lin->m_cdelt = 0;
d75 3
a77 3
       lin->crpix == 0 ||
       lin->pc    == 0 ||
       lin->cdelt == 0) {
d85 1
a85 1
      if (alloc || lin->crpix == 0) {
d101 1
a101 1
      if (alloc || lin->pc == 0) {
d118 1
a118 1
      if (alloc || lin->cdelt == 0) {
d142 3
a144 3
   lin->piximg = 0;
   lin->imgpix = 0;
   lin->i_naxis = 0;
d193 1
a193 1
   if (linsrc == 0) return 1;
d234 1
a234 1
   if (lin == 0) return 1;
d239 3
a241 3
         if (lin->crpix == lin->m_crpix) lin->crpix = 0;
         if (lin->pc    == lin->m_pc)    lin->pc    = 0;
         if (lin->cdelt == lin->m_cdelt) lin->cdelt = 0;
d251 3
a253 3
   lin->m_crpix = 0;
   lin->m_pc    = 0;
   lin->m_cdelt = 0;
d262 2
a263 2
   lin->piximg = 0;
   lin->imgpix = 0;
d280 1
a280 1
   if (lin == 0) return 1;
d292 1
a292 1
      printf("  %- 11.4g", lin->crpix[i]);
d301 1
a301 1
         printf("  %- 11.4g", lin->pc[k++]);
d309 1
a309 1
      printf("  %- 11.4g", lin->cdelt[i]);
d315 1
a315 1
   if (lin->piximg == 0) {
d322 1
a322 1
            printf("  %- 11.4g", lin->piximg[k++]);
d328 1
a328 1
   if (lin->imgpix == 0) {
d335 1
a335 1
            printf("  %- 11.4g", lin->imgpix[k++]);
d366 1
a366 1
   if (lin == 0) return 1;
d397 2
a398 2
      lin->piximg = 0;
      lin->imgpix = 0;
d460 1
a460 1
   if (lin == 0) return 1;
d522 1
a522 1
   if (lin == 0) return 1;
@


3.6
log
@WCSLIB 3.6: "error status/code/number" is now referred to consistently as the
"status return value"; replaced "error" with "failed" in status messages.
@
text
@d3 2
a4 2
*   WCSLIB 3.6 - an implementation of the FITS WCS convention.
*   Copyright (C) 1995-2004, Mark Calabretta
d6 4
a9 4
*   This library is free software; you can redistribute it and/or modify it
*   under the terms of the GNU Library General Public License as published
*   by the Free Software Foundation; either version 2 of the License, or (at
*   your option) any later version.
d11 4
a14 4
*   This library is distributed in the hope that it will be useful, but
*   WITHOUT ANY WARRANTY; without even the implied warranty of
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library
*   General Public License for more details.
d16 3
a18 3
*   You should have received a copy of the GNU Library General Public License
*   along with this library; if not, write to the Free Software Foundation,
*   Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
d30 1
a30 1
*   $Id: lin.c,v 3.5 2004/06/28 02:02:37 mcalabre Exp mcalabre $
d75 3
a77 3
       lin->crpix == (double *)0 ||
       lin->pc    == (double *)0 ||
       lin->cdelt == (double *)0) {
d85 1
a85 1
      if (alloc || lin->crpix == (double *)0) {
d91 1
a91 1
            if (!(lin->crpix = (double *)calloc(naxis, sizeof(double)))) {
d101 1
a101 1
      if (alloc || lin->pc == (double *)0) {
d107 1
a107 1
            if (!(lin->pc = (double *)calloc(naxis*naxis, sizeof(double)))) {
d118 1
a118 1
      if (alloc || lin->cdelt == (double *)0) {
d124 1
a124 1
            if (!(lin->cdelt = (double *)calloc(naxis, sizeof(double)))) {
d392 1
a392 1
         /* Free memory which may have been allocated previously. */
d397 2
a398 2
      lin->piximg = (double*)0;
      lin->imgpix = (double*)0;
d404 1
a404 1
            /* Free memory which may have been allocated previously. */
d410 1
a410 1
         if (!(lin->piximg = (double*)calloc(n*n, sizeof(double)))) {
d414 1
a414 1
         if (!(lin->imgpix = (double*)calloc(n*n, sizeof(double)))) {
d455 2
a456 1
   register double *img, *pix, *piximg;
d469 2
a470 2
   pix = (double *)pixcrd;
   img = (double *)imgcrd;
d517 2
a518 1
   register double *img, *imgpix, *pix;
d531 2
a532 2
   img = (double *)imgcrd;
   pix = (double *)pixcrd;
d581 2
a582 2
   if (!(mxl = (int*)calloc(n, sizeof(int)))) return 2;
   if (!(lxm = (int*)calloc(n, sizeof(int)))) {
d587 1
a587 1
   if (!(rowmax = (double*)calloc(n, sizeof(double)))) {
d593 1
a593 1
   if (!(lu = (double*)calloc(n*n, sizeof(double)))) {
d603 1
a603 1
      /* Vector which records row interchanges. */
@


3.5
log
@WCSLIB 3.5: use calloc() in place of malloc() in allocating memory for
arrays, and replace malloc.h with stdlib.h for all platforms; in linfree(),
check that lin.flag != -1 before testing lin.m_flag when freeing memory
allocated by linini(); added the alternate version code to FITS WCS keywords
mentioned in comments.
@
text
@d3 1
a3 1
*   WCSLIB 3.5 - an implementation of the FITS WCS convention.
d30 1
a30 1
*   $Id: lin.c,v 3.4 2004/02/11 00:15:03 mcalabre Exp mcalabre $
d40 1
a40 1
/* Map error number to error message for each function. */
d44 1
a44 1
   "Memory allocation error",
@


3.4
log
@WCSLIB 3.4
@
text
@d3 1
a3 1
*   WCSLIB 3.4 - an implementation of the FITS WCS convention.
d29 2
a30 1
*   $Id: lin.c,v 3.3 2003/10/22 07:20:56 mcalabre Exp mcalabre $
d34 1
d45 1
a45 2
   "PC matrix is singular"};

a46 5
#if defined(__convexc__) || defined(__APPLE__)
#include <stdlib.h>
#else
#include <malloc.h>
#endif
d56 1
a56 1
   int i, j, mem;
d91 1
a91 2
            mem = naxis * sizeof(double);
            if ((lin->crpix = (double *)malloc(mem)) == (double *)0) {
d107 1
a107 2
            mem = naxis * naxis * sizeof(double);
            if ((lin->pc = (double *)malloc(mem)) == (double *)0) {
d124 1
a124 2
            mem = naxis * sizeof(double);
            if ((lin->cdelt = (double *)malloc(mem)) == (double *)0) {
d151 1
a151 1
   /* CRPIXj defaults to 0.0. */
d157 1
a157 1
   /* PCi_j defaults to the unit matrix. */
d162 1
a162 1
            *(pc++) = 1.0;
d164 1
a164 1
            *(pc++) = 0.0;
d166 1
d171 1
a171 1
   /* CDELTi defaults to 1.0. */
d236 11
a246 9
   /* Free memory allocated by linini(). */
   if (lin->m_flag == LINSET) {
      if (lin->crpix == lin->m_crpix) lin->crpix = 0;
      if (lin->pc    == lin->m_pc)    lin->pc    = 0;
      if (lin->cdelt == lin->m_cdelt) lin->cdelt = 0;

      if (lin->m_crpix) free(lin->m_crpix);
      if (lin->m_pc)    free(lin->m_pc);
      if (lin->m_cdelt) free(lin->m_cdelt);
d363 1
a363 1
   int i, j, mem, n, status;
d410 1
a410 2
         mem = n * n * sizeof(double);
         if ((lin->piximg = (double*)malloc(mem)) == (double*)0) {
d414 1
a414 1
         if ((lin->imgpix = (double*)malloc(mem)) == (double*)0) {
d432 3
a434 1
      if (status = matinv(n, lin->piximg, lin->imgpix)) return status;
d574 1
a574 1
   int    itemp, mem, *mxl, *lxm, pivot;
d579 2
a580 3
   mem = n * sizeof(int);
   if ((mxl = (int*)malloc(mem)) == (int*)0) return 2;
   if ((lxm = (int*)malloc(mem)) == (int*)0) {
d585 1
a585 2
   mem = n * sizeof(double);
   if ((rowmax = (double*)malloc(mem)) == (double*)0) {
d591 1
a591 2
   mem *= n;
   if ((lu = (double*)malloc(mem)) == (double*)0) {
@


3.3
log
@WCSLIB 3.3: linprt() now checks that the linprm struct has been initialized.
@
text
@d3 2
a4 2
*   WCSLIB 3.3 - an implementation of the FITS WCS convention.
*   Copyright (C) 1995-2003, Mark Calabretta
d29 1
a29 1
*   $Id: lin.c,v 3.2 2003/09/09 04:04:04 mcalabre Exp mcalabre $
@


3.2
log
@WCSLIB 3.2: in linini(), initialize memory management if linprm.flag == -1;
test for null linprm pointer given as function argument; rationalized
function return codes and messages.
@
text
@d3 1
a3 1
*   WCSLIB 3.2 - an implementation of the FITS WCS convention.
d29 1
a29 1
*   $Id: lin.c,v 3.1 2003/04/28 03:50:41 mcalabre Exp mcalabre $
d286 5
d315 1
a315 1
   printf("\n\n");
@


3.1
log
@WCSLIB 3.1
Revised printing of piximg and imgpix in linprt().
@
text
@d3 1
a3 1
*   WCSLIB 3.1 - an implementation of the FITS WCS convention.
d29 1
a29 1
*   $Id: lin.c,v 3.0 2003/04/01 04:10:53 mcalabre Exp mcalabre $
d39 1
a39 1
const char *linini_errmsg[] = {
d41 1
a41 28
   "Memory allocation error"};

const char *lincpy_errmsg[] = {
   0,
   "Memory allocation error"};

const char *linset_errmsg[] = {
   0,
   "Memory allocation error",
   "PC matrix is singular"};

const char *linp2x_errmsg[] = {
   0,
   "Memory allocation error",
   "PC matrix is singular"};

const char *linx2p_errmsg[] = {
   0,
   "Memory allocation error",
   "PC matrix is singular"};

const char *linrev_errmsg[] = {
   0,
   "Memory allocation error",
   "PC matrix is singular"};

const char *linfwd_errmsg[] = {
   0,
d63 1
d65 1
a65 1
      return 1;
d68 1
a68 1
   if (lin->m_flag != LINSET) {
d97 1
a97 1
               return 1;
d115 1
a115 1
               return 1;
d133 1
a133 1
               return 1;
d199 2
d203 1
a203 1
      return 1;
d240 2
d270 2
d362 1
a362 1
   int i, j, mem, n;
d365 2
d411 1
a411 1
            return 1;
d416 1
a416 1
            return 1;
d432 1
a432 1
      if (matinv(n, lin->piximg, lin->imgpix)) return 2;
d451 1
a451 1
   int err, i, j, k, n;
a454 1
   n = lin->naxis;
d456 2
d459 1
a459 1
      if (err = linset(lin)) return err;
d462 2
d513 1
a513 1
   int err, i, j, k, n;
a515 1
   n = lin->naxis;
d517 2
d520 1
a520 1
      if (err = linset(lin)) return err;
d523 2
d578 1
a578 1
   if ((mxl = (int*)malloc(mem)) == (int*)0) return 1;
d581 1
a581 1
      return 1;
d588 1
a588 1
      return 1;
d596 1
a596 1
      return 1;
d620 1
a620 1
         return 2;
@


3.0
log
@WCSLIB 3.0
@
text
@d3 1
a3 1
*   WCSLIB 3.0 - an implementation of the FITS WCS convention.
d29 1
a29 1
*   $Id: lin.c,v 2.7 2002/01/30 06:04:03 mcalabre Exp $
d334 10
a343 5
   k = 0;
   for (i = 0; i < lin->naxis; i++) {
      printf("piximg[%d][]:", i);
      for (j = 0; j < lin->naxis; j++) {
         printf("  %- 11.4g", lin->piximg[k++]);
a344 1
      printf("\n");
d347 10
a356 5
   k = 0;
   for (i = 0; i < lin->naxis; i++) {
      printf("imgpix[%d][]:", i);
      for (j = 0; j < lin->naxis; j++) {
         printf("  %- 11.4g", lin->imgpix[k++]);
a357 1
      printf("\n");
@


2.8
log
@Added a conditional compilation directive for Apple's MacOS X.
@
text
@d1 1
a1 1
/*=============================================================================
d3 2
a4 2
*   WCSLIB - an implementation of the FITS WCS proposal.
*   Copyright (C) 1995-2002, Mark Calabretta
d22 4
a25 4
*      Postal address: Dr. Mark Calabretta,
*                      Australia Telescope National Facility,
*                      P.O. Box 76,
*                      Epping, NSW, 2121,
a27 134
*=============================================================================
*
*   C routines which implement the FITS World Coordinate System (WCS)
*   convention.
*
*   Summary of routines
*   -------------------
*   These utility routines apply the linear transformation defined by the WCS
*   FITS header cards.  There are separate routines for the image-to-pixel,
*   linfwd(), and pixel-to-image, linrev(), transformations.
*
*   An initialization routine, linset(), computes intermediate values from
*   the transformation parameters but need not be called explicitly - see the
*   explanation of lin.flag below.
*
*   An auxiliary matrix inversion routine, matinv(), is included.  It uses
*   LU-triangular factorization with scaled partial pivoting.
*
*
*   Initialization routine; linset()
*   --------------------------------
*   Initializes members of a linprm data structure which hold intermediate
*   values.  Note that this routine need not be called directly; it will be
*   invoked by linfwd() and linrev() if the "flag" structure member is
*   anything other than a predefined magic value.
*
*   Given and/or returned:
*      lin      linprm*  Linear transformation parameters (see below).
*
*   Function return value:
*               int      Error status
*                           0: Success.
*                           1: Memory allocation error.
*                           2: PC matrix is singular.
*
*   Forward transformation; linfwd()
*   --------------------------------
*   Compute pixel coordinates from image coordinates.  Note that where
*   celestial coordinate systems are concerned the image coordinates
*   correspond to (x,y) in the plane of projection, not celestial (lng,lat).
*
*   Given:
*      imgcrd   const double[]
*                        Image (world) coordinate.
*
*   Given and returned:
*      lin      linprm*  Linear transformation parameters (see below).
*
*   Returned:
*      pixcrd   d[]      Pixel coordinate.
*
*   Function return value:
*               int      Error status
*                           0: Success.
*                           1: The transformation is not invertible.
*
*   Reverse transformation; linrev()
*   --------------------------------
*   Compute image coordinates from pixel coordinates.  Note that where
*   celestial coordinate systems are concerned the image coordinates
*   correspond to (x,y) in the plane of projection, not celestial (lng,lat).
*
*   Given:
*      pixcrd   const double[]
*                        Pixel coordinate.
*
*   Given and/or returned:
*      lin      linprm*  Linear transformation parameters (see below).
*
*   Returned:
*      imgcrd   d[]      Image (world) coordinate.
*
*   Function return value:
*               int      Error status
*                           0: Success.
*                           1: Error.
*
*   Linear transformation parameters
*   --------------------------------
*   The linprm struct consists of the following:
*
*      int flag
*         This flag must be set to zero whenever any of the following members
*         are set or modified.  This signals the initialization routine,
*         linset(), to recompute intermediaries.
*      int naxis
*         Number of image axes.
*      double *crpix
*         Pointer to the first element of an array of double containing the
*         coordinate reference pixel, CRPIXn.
*      double *pc
*         Pointer to the first element of the PC (pixel coordinate)
*         transformation matrix.  The expected order is
*
*            lin.pc = {PC1_1, PC1_2, PC2_1, PC2_2};
*
*         This may be conveniently constructed from a two-dimensional array
*         via
*
*            double m[2][2] = {{PC1_1, PC1_2},
*                              {PC2_1, PC2_2}};
*
*         which is equivalent to,
*
*            double m[2][2];
*            m[0][0] = PC1_1;
*            m[0][1] = PC1_2;
*            m[1][0] = PC2_1;
*            m[1][1] = PC2_2;
*
*         for which the storage order is
*
*            PC1_1, PC1_2, PC2_1, PC2_2
*
*         so it would be legitimate to set lin.pc = *m.
*      double *cdelt
*         Pointer to the first element of an array of double containing the
*         coordinate increments, CDELTn.
*
*   The remaining members of the linprm struct are maintained by the
*   initialization routine and should not be modified.
*
*      double *piximg
*         Pointer to the first element of the matrix containing the product
*         of the CDELTn diagonal matrix and the PC matrix.
*      double *imgpix
*         Pointer to the first element of the inverse of the piximg matrix.
*
*   linset allocates storage for the above arrays using malloc().  Note,
*   however, that these routines do not free this storage so if a linprm
*   variable has itself been malloc'd then these structure members must be
*   explicitly freed before the linprm variable is free'd otherwise a memory
*   leak will result.
*
d29 1
a29 1
*   $Id: lin.c,v 2.7 2001/11/15 03:24:48 mcalabre Exp mcalabre $
d32 1
d36 2
d39 8
d52 6
a57 1
const char *linfwd_errmsg[] = {
d67 5
d79 290
d374 2
a375 1
   int i, ij, j, mem, n;
d379 17
a395 9
   /* Allocate memory for internal arrays. */
   mem = n * n * sizeof(double);
   lin->piximg = (double*)malloc(mem);
   if (lin->piximg == (double*)0) return 1;

   lin->imgpix = (double*)malloc(mem);
   if (lin->imgpix == (double*)0) {
      free(lin->piximg);
      return 1;
d398 41
a438 4
   /* Compute the pixel-to-image transformation matrix. */
   for (i = 0, ij = 0; i < n; i++) {
      for (j = 0; j < n; j++, ij++) {
         lin->piximg[ij] = lin->cdelt[i] * lin->pc[ij];
d440 3
a444 2
   /* Compute the image-to-pixel transformation matrix. */
   if (matinv(n, lin->piximg, lin->imgpix)) return 2;
d453 1
a453 1
int linfwd(imgcrd, lin, pixcrd)
a454 1
const double imgcrd[];
d456 3
a458 1
double pixcrd[];
d461 3
a463 1
   int i, ij, j, n;
d468 1
a468 1
      if (linset(lin)) return 1;
d471 13
a483 4
   for (i = 0, ij = 0; i < n; i++) {
      pixcrd[i] = 0.0;
      for (j = 0; j < n; j++, ij++) {
         pixcrd[i] += lin->imgpix[ij] * imgcrd[j];
d485 16
a500 1
   }
d502 3
a504 2
   for (j = 0; j < n; j++) {
      pixcrd[j] += lin->crpix[j];
d512 1
a512 1
int linrev(pixcrd, lin, imgcrd)
a513 1
const double pixcrd[];
d515 3
a517 1
double imgcrd[];
d520 2
a521 2
   int i, ij, j, n;
   double temp;
d526 1
a526 1
      if (linset(lin)) return 1;
d529 28
a556 3
   for (i = 0; i < n; i++) {
      imgcrd[i] = 0.0;
   }
d558 2
a559 4
   for (j = 0; j < n; j++) {
      temp = pixcrd[j] - lin->crpix[j];
      for (i = 0, ij = j; i < n; i++, ij+=n) {
         imgcrd[i] += lin->piximg[ij] * temp;
d570 1
a570 1
const int n;
@


2.7
log
@Changed date in copyright notice.
@
text
@d4 1
a4 1
*   Copyright (C) 1995-2001, Mark Calabretta
d163 1
a163 1
*   $Id: lin.c,v 2.6 2000/03/10 01:14:42 mcalabre Exp mcalabre $
d186 1
a186 1
#ifdef __convexc__
@


2.6
log
@Augmented prologue concerning the order of PC matrix elements in the linprm
struct.
@
text
@d4 1
a4 1
*   Copyright (C) 1995-2000, Mark Calabretta
d129 1
a129 1
*         
d163 1
a163 1
*   $Id: lin.c,v 2.5 1999/06/16 00:03:19 mcalabre Exp mcalabre $
@


2.5
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
*   Copyright (C) 1995-1999, Mark Calabretta
d120 23
a142 1
*         transformation matrix.
d163 1
a163 1
*   $Id: lin.c,v 2.4 1998/02/25 07:05:50 mcalabre Exp mcalabre $
@


2.4
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
*   Copyright (C) 1995-1998, Mark Calabretta
d141 1
a141 1
*   $Id: lin.c,v 2.3 1996/05/24 07:25:36 mcalabre Exp mcalabre $
@


2.3
log
@Include lin.h earlier to handle const definition for K&R compiler.
@
text
@d4 1
a4 1
*   Copyright (C) 1995,1996 Mark Calabretta
d141 1
a141 1
*   $Id: lin.c,v 2.2 1996/05/07 20:18:03 mcalabre Exp mcalabre $
@


2.2
log
@Replaced usage of alloca()  with malloc() and free() for portability.
Added const-correctness to function arguments.
Added external arrays of error messages indexed by function return value.
@
text
@d141 1
a141 1
*   $Id: lin.c,v 2.1 1995/09/11 07:59:38 mcalabre Exp mcalabre $
d144 3
a168 3

#include <math.h>
#include "lin.h"
@


2.1
log
@Initial revision
@
text
@d4 1
a4 1
*   Copyright (C) 1995, Mark Calabretta
d70 2
a71 1
*      imgcrd   d[]      Image (world) coordinate.
d91 2
a92 1
*      pixcrd   d[]      Pixel coordinate.
d126 1
a126 2
*   initialization routine and should not be modified.  Storage will be
*   allocated for these arrays via malloc().
d134 6
d141 1
a141 1
*   $Id$
d144 17
a163 1
#include <alloca.h>
d185 4
a188 1
   if (lin->imgpix == (double*)0) return 1;
d209 1
a209 1
double imgcrd[];
d240 1
a240 1
double pixcrd[];
d272 3
a274 2
int n;
double mat[], inv[];
d284 5
a288 2
   if ((mxl = (int*)alloca(mem)) == (int*)0) return 1;
   if ((lxm = (int*)alloca(mem)) == (int*)0) return 1;
d291 5
a295 1
   if ((rowmax = (double*)alloca(mem)) == (double*)0) return 1;
d298 6
a303 1
   if ((lu = (double*)alloca(mem)) == (double*)0) return 1;
d321 7
a327 1
      if (rowmax[i] == 0.0) return 2;
d415 5
@
