1 /*
   2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 import java.foreign.Libraries;
  25 import java.foreign.Library;
  26 import java.foreign.Scope;
  27 import java.foreign.memory.DoubleComplex;
  28 import java.foreign.memory.FloatComplex;
  29 import java.foreign.memory.LongDoubleComplex;
  30 import java.lang.invoke.MethodHandle;
  31 import java.lang.invoke.MethodHandles;
  32 import org.testng.annotations.BeforeTest;
  33 import org.testng.annotations.Test;
  34 import org.c99.libcomplex_aux;
  35 import org.c99.mycomplex;
  36 
  37 import static org.testng.Assert.assertEquals;
  38 import static org.testng.Assert.assertTrue;
  39 
  40 // FIXME: long double _Complex is not yet supported because long double is not
  41 // yet supported. Fix this test to include long double _Complex when binder
  42 // supports long double.
  43 
  44 /*
  45  * @test
  46  * @requires os.family != "windows"
  47  * @bug 8213013
  48  * @summary jextract does not handle C99 _Complex type
  49  * @library ..
  50  * @run driver JtregJextract -t org.c99 -- mycomplex.h
  51  * @run driver JtregJextract -t org.c99 -- libcomplex_aux.h
  52  * @run testng ComplexTest
  53  */
  54 public class ComplexTest {
  55 
  56     private static final double TOLERANCE = 0.0001;
  57     private static final float TOLERANCEF = 0.0001f;
  58 
  59     private mycomplex comlib;
  60     private libcomplex_aux auxlib;
  61 
  62     @BeforeTest
  63     public void init() {
  64         comlib = Libraries.bind(MethodHandles.lookup(), mycomplex.class);
  65         Library l = Libraries.loadLibrary(MethodHandles.lookup(), "complex_aux");
  66         auxlib = Libraries.bind(libcomplex_aux.class, l);
  67     }
  68 
  69     @Test
  70     public void testDoubleComplex() {
  71         try (Scope s = Scope.globalScope().fork()) {
  72             // check Euler's identity
  73             DoubleComplex dc = s.allocateStruct(DoubleComplex.class);
  74             dc.real$set(0.0);
  75             dc.imag$set(Math.PI);
  76             dc = comlib.cexp(dc);
  77             assertEquals(dc.real$get(), -1.0, TOLERANCE);
  78             assertEquals(dc.imag$get(), 0.0, TOLERANCE);
  79 
  80             // arg of i is pi/2
  81             dc.real$set(0.0);
  82             dc.imag$set(1.0);
  83             assertEquals(comlib.carg(dc), Math.PI/2.0, TOLERANCE);
  84 
  85             // abs of 1+i is sqrt(2)
  86             dc.real$set(1.0);
  87             dc.imag$set(1.0);
  88             assertEquals(comlib.cabs(dc), Math.sqrt(2.0), TOLERANCE);
  89 
  90             // conjugate of 1+i is 1-i
  91             dc = comlib.conj(dc);
  92             assertEquals(comlib.creal(dc), 1.0, TOLERANCE);
  93             assertEquals(comlib.cimag(dc), -1.0, TOLERANCE);
  94 
  95             // test callback
  96             dc = auxlib.f(dc, s.allocateCallback(c -> c));
  97             assertEquals(comlib.creal(dc), 1.0f, TOLERANCE);
  98             assertEquals(comlib.cimag(dc), -1.0f, TOLERANCE);
  99         }
 100     }
 101 
 102     @Test
 103     public void testFloatComplex() {
 104         try (Scope s = Scope.globalScope().fork()) {
 105             // check Euler's identity
 106             FloatComplex fc = s.allocateStruct(FloatComplex.class);
 107             fc.real$set(0.0f);
 108             fc.imag$set((float)Math.PI);
 109             fc = comlib.cexpf(fc);
 110             assertEquals(fc.real$get(), -1.0f, TOLERANCEF);
 111             assertEquals(fc.imag$get(), 0.0f, TOLERANCEF);
 112 
 113             // arg of i is pi/2
 114             fc.real$set(0.0f);
 115             fc.imag$set(1.0f);
 116             assertEquals(comlib.cargf(fc), (float)Math.PI/2.0, TOLERANCEF);
 117 
 118             // abs of 1+i is sqrt(2)
 119             fc.real$set(1.0f);
 120             fc.imag$set(1.0f);
 121             assertEquals(comlib.cabsf(fc), (float)Math.sqrt(2.0), TOLERANCEF);
 122 
 123             // conjugate of 1+i is 1-i
 124             fc = comlib.conjf(fc);
 125             assertEquals(comlib.crealf(fc), 1.0f, TOLERANCEF);
 126             assertEquals(comlib.cimagf(fc), -1.0f, TOLERANCEF);
 127 
 128             // test callback
 129             fc = auxlib.ff(fc, s.allocateCallback(c -> c));
 130             assertEquals(comlib.crealf(fc), 1.0f, TOLERANCEF);
 131             assertEquals(comlib.cimagf(fc), -1.0f, TOLERANCEF);
 132         }
 133     }
 134 
 135     @Test
 136     public void testLongDoubleComplex() {
 137         try (Scope s = Scope.globalScope().fork()) {
 138             // check Euler's identity
 139             LongDoubleComplex ldc = s.allocateStruct(LongDoubleComplex.class);
 140             ldc.real$set(0.0);
 141             ldc.imag$set(Math.PI);
 142             System.err.println(ldc.real$get());
 143             ldc = comlib.cexpl(ldc);
 144             assertEquals(ldc.real$get(), -1.0, TOLERANCE);
 145             assertEquals(ldc.imag$get(), 0.0, TOLERANCE);
 146 
 147             // arg of i is pi/2
 148             ldc.real$set(0.0);
 149             ldc.imag$set(1.0);
 150             assertEquals(comlib.cargl(ldc), Math.PI/2.0, TOLERANCE);
 151 
 152             // abs of 1+i is sqrt(2)
 153             ldc.real$set(1.0);
 154             ldc.imag$set(1.0);
 155             assertEquals(comlib.cabsl(ldc), Math.sqrt(2.0), TOLERANCE);
 156 
 157             // conjugate of 1+i is 1-i
 158             ldc = comlib.conjl(ldc);
 159             assertEquals(comlib.creall(ldc), 1.0, TOLERANCE);
 160             assertEquals(comlib.cimagl(ldc), -1.0, TOLERANCE);
 161 
 162             // test callback
 163             ldc = auxlib.fl(ldc, s.allocateCallback(c -> c));
 164             assertEquals(comlib.creall(ldc), 1.0f, TOLERANCE);
 165             assertEquals(comlib.cimagl(ldc), -1.0f, TOLERANCE);
 166         }
 167     }
 168 }