int TriShapeAndDrv(int p, double par[2], double N[], double dN[][2]) {
  int i, j, nshp = 0;
  double L[3];
  if (p > 2)
    return nshp;
  L[0] = par[0];
  L[1] = par[1];
  L[2] = 1.0e0 - par[0] - par[1];
  for (i = 0; i < 3; i++) {
    N[i] = L[i];
    if (i == 2)
      dN[i][0] = dN[i][1] = -1.0e0;
    else {
      for (j = 0; j < 2; j++) {
        if (i == j)
          dN[i][j] = 1.0e0;
        else
          dN[i][j] = 0.0e0;
      }
    }
  }
  nshp = 3;
  if (p > 1) {
    N[3] = -2.0e0 * L[0] * L[1];
    N[4] = -2.0e0 * L[1] * L[2];
    N[5] = -2.0e0 * L[0] * L[2];
    dN[3][0] = -2.0e0 * L[1];
    dN[3][1] = -2.0e0 * L[0];
    dN[4][0] = 2.0e0 * L[1];
    dN[4][1] = -2.0e0 + 2.0e0 * L[0] + 4.0e0 * L[1];
    dN[5][0] = -2.0e0 + 4.0e0 * L[0] + 2.0e0 * L[1];
    dN[5][1] = 2.0e0 * L[0];
    nshp = 6;
  }
  return nshp;
}


x86 assembly (clang, -O0):
<TriShapeAndDrv>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
movl   $0x0,-0x2c(%rbp)
cmpl   $0x2,-0x8(%rbp)
jle    112f <TriShapeAndDrv+0x2f>
mov    -0x2c(%rbp),%eax
mov    %eax,-0x4(%rbp)
jmp    138b <TriShapeAndDrv+0x28b>
mov    -0x10(%rbp),%rax
movsd  (%rax),%xmm0
movsd  %xmm0,-0x50(%rbp)
mov    -0x10(%rbp),%rax
movsd  0x8(%rax),%xmm0
movsd  %xmm0,-0x48(%rbp)
mov    -0x10(%rbp),%rax
movsd  0xeaa(%rip),%xmm0
subsd  (%rax),%xmm0
mov    -0x10(%rbp),%rax
subsd  0x8(%rax),%xmm0
movsd  %xmm0,-0x40(%rbp)
movl   $0x0,-0x24(%rbp)
cmpl   $0x3,-0x24(%rbp)
jge    125e <TriShapeAndDrv+0x15e>
movslq -0x24(%rbp),%rax
movsd  -0x50(%rbp,%rax,8),%xmm0
mov    -0x18(%rbp),%rax
movslq -0x24(%rbp),%rcx
movsd  %xmm0,(%rax,%rcx,8)
cmpl   $0x2,-0x24(%rbp)
jne    11d6 <TriShapeAndDrv+0xd6>
mov    -0x20(%rbp),%rax
movslq -0x24(%rbp),%rcx
shl    $0x4,%rcx
add    %rcx,%rax
movsd  0xe6f(%rip),%xmm0
movsd  %xmm0,0x8(%rax)
mov    -0x20(%rbp),%rax
movslq -0x24(%rbp),%rcx
shl    $0x4,%rcx
add    %rcx,%rax
movsd  0xe53(%rip),%xmm0
movsd  %xmm0,(%rax)
jmp    124b <TriShapeAndDrv+0x14b>
movl   $0x0,-0x28(%rbp)
cmpl   $0x2,-0x28(%rbp)
jge    1246 <TriShapeAndDrv+0x146>
mov    -0x24(%rbp),%eax
cmp    -0x28(%rbp),%eax
jne    1218 <TriShapeAndDrv+0x118>
mov    -0x20(%rbp),%rax
movslq -0x24(%rbp),%rcx
shl    $0x4,%rcx
add    %rcx,%rax
movslq -0x28(%rbp),%rcx
movsd  0xdf2(%rip),%xmm0
movsd  %xmm0,(%rax,%rcx,8)
jmp    1233 <TriShapeAndDrv+0x133>
mov    -0x20(%rbp),%rax
movslq -0x24(%rbp),%rcx
shl    $0x4,%rcx
add    %rcx,%rax
movslq -0x28(%rbp),%rcx
xorps  %xmm0,%xmm0
movsd  %xmm0,(%rax,%rcx,8)
jmp    1238 <TriShapeAndDrv+0x138>
mov    -0x28(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x28(%rbp)
jmp    11dd <TriShapeAndDrv+0xdd>
jmp    124b <TriShapeAndDrv+0x14b>
jmp    1250 <TriShapeAndDrv+0x150>
mov    -0x24(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x24(%rbp)
jmp    116f <TriShapeAndDrv+0x6f>
movl   $0x3,-0x2c(%rbp)
cmpl   $0x1,-0x8(%rbp)
jle    1385 <TriShapeAndDrv+0x285>
movsd  0xda1(%rip),%xmm0
mulsd  -0x50(%rbp),%xmm0
mulsd  -0x48(%rbp),%xmm0
mov    -0x18(%rbp),%rax
movsd  %xmm0,0x18(%rax)
movsd  0xd86(%rip),%xmm0
mulsd  -0x48(%rbp),%xmm0
mulsd  -0x40(%rbp),%xmm0
mov    -0x18(%rbp),%rax
movsd  %xmm0,0x20(%rax)
movsd  0xd6b(%rip),%xmm0
mulsd  -0x50(%rbp),%xmm0
mulsd  -0x40(%rbp),%xmm0
mov    -0x18(%rbp),%rax
movsd  %xmm0,0x28(%rax)
movsd  0xd50(%rip),%xmm0
mulsd  -0x48(%rbp),%xmm0
mov    -0x20(%rbp),%rax
movsd  %xmm0,0x30(%rax)
movsd  0xd3a(%rip),%xmm0
mulsd  -0x50(%rbp),%xmm0
mov    -0x20(%rbp),%rax
movsd  %xmm0,0x38(%rax)
movsd  0xd14(%rip),%xmm0
mulsd  -0x48(%rbp),%xmm0
mov    -0x20(%rbp),%rax
movsd  %xmm0,0x40(%rax)
movsd  -0x50(%rbp),%xmm1
addsd  %xmm1,%xmm1
movsd  0xd05(%rip),%xmm0
addsd  %xmm0,%xmm1
movsd  -0x48(%rbp),%xmm0
movsd  0xcec(%rip),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x20(%rbp),%rax
movsd  %xmm0,0x48(%rax)
movsd  -0x50(%rbp),%xmm1
movsd  0xcce(%rip),%xmm0
mulsd  %xmm0,%xmm1
movsd  0xcca(%rip),%xmm0
addsd  %xmm0,%xmm1
movsd  -0x48(%rbp),%xmm0
addsd  %xmm0,%xmm0
addsd  %xmm1,%xmm0
mov    -0x20(%rbp),%rax
movsd  %xmm0,0x50(%rax)
movsd  0xc98(%rip),%xmm0
mulsd  -0x50(%rbp),%xmm0
mov    -0x20(%rbp),%rax
movsd  %xmm0,0x58(%rax)
movl   $0x6,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
mov    %eax,-0x4(%rbp)
mov    -0x4(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<TriShapeAndDrv>:
xor    %eax,%eax
cmp    $0x2,%edi
jg     11d7 <TriShapeAndDrv+0xd7>
movupd (%rsi),%xmm0
movsd  0xee9(%rip),%xmm2
xorpd  %xmm3,%xmm3
unpcklpd %xmm2,%xmm3
subsd  %xmm0,%xmm2
movapd %xmm0,%xmm1
unpckhpd %xmm0,%xmm1
subsd  %xmm1,%xmm2
movlpd %xmm0,(%rdx)
movsd  0xec5(%rip),%xmm4
movupd %xmm4,(%rcx)
movhpd %xmm0,0x8(%rdx)
movupd %xmm3,0x10(%rcx)
movsd  %xmm2,0x10(%rdx)
movapd 0xeba(%rip),%xmm3
movupd %xmm3,0x20(%rcx)
mov    $0x3,%eax
jne    11d7 <TriShapeAndDrv+0xd7>
movapd 0xeb6(%rip),%xmm3
movapd %xmm0,%xmm4
mulpd  %xmm3,%xmm4
movapd %xmm0,%xmm5
shufpd $0x1,%xmm2,%xmm5
mulpd  %xmm4,%xmm5
movupd %xmm5,0x18(%rdx)
mulsd  %xmm4,%xmm2
movsd  %xmm2,0x28(%rdx)
shufpd $0x1,%xmm4,%xmm4
movupd %xmm4,0x30(%rcx)
movapd %xmm1,%xmm2
addsd  %xmm1,%xmm2
movsd  %xmm2,0x40(%rcx)
movapd %xmm0,%xmm2
unpcklpd %xmm0,%xmm2
mulpd  0xe7c(%rip),%xmm2
addpd  %xmm3,%xmm2
mulpd  0xe80(%rip),%xmm1
addpd  %xmm2,%xmm1
movupd %xmm1,0x48(%rcx)
addsd  %xmm0,%xmm0
movsd  %xmm0,0x58(%rcx)
mov    $0x6,%eax
ret

LLVM IR (-O0):
define i32 @TriShapeAndDrv(i32 %0, double* %1, double* %2, [2 x double]* %3) {
%5 = alloca i32
%6 = alloca i32
%7 = alloca double*
%8 = alloca double*
%9 = alloca [2 x double]*
%10 = alloca i32
%11 = alloca i32
%12 = alloca i32
%13 = alloca [3 x double]
store i32 %0, i32* %6
store double* %1, double** %7
store double* %2, double** %8
store [2 x double]* %3, [2 x double]** %9
store i32 0, i32* %12
%14 = load i32, i32* %6
%15 = icmp sgt i32 %14, 2
br i1 %15, label %16, label %18
16: ; preds = %4
%17 = load i32, i32* %12
store i32 %17, i32* %5
br label %166
18: ; preds = %4
%19 = load double*, double** %7
%20 = getelementptr inbounds double, double* %19, i64 0
%21 = load double, double* %20
%22 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 0
store double %21, double* %22
%23 = load double*, double** %7
%24 = getelementptr inbounds double, double* %23, i64 1
%25 = load double, double* %24
%26 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 1
store double %25, double* %26
%27 = load double*, double** %7
%28 = getelementptr inbounds double, double* %27, i64 0
%29 = load double, double* %28
%30 = fsub double 1.000000e+00, %29
%31 = load double*, double** %7
%32 = getelementptr inbounds double, double* %31, i64 1
%33 = load double, double* %32
%34 = fsub double %30, %33
%35 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 2
store double %34, double* %35
store i32 0, i32* %10
br label %36
36: ; preds = %91, %18
%37 = load i32, i32* %10
%38 = icmp slt i32 %37, 3
br i1 %38, label %39, label %94
39: ; preds = %36
%40 = load i32, i32* %10
%41 = sext i32 %40 to i64
%42 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 %41
%43 = load double, double* %42
%44 = load double*, double** %8
%45 = load i32, i32* %10
%46 = sext i32 %45 to i64
%47 = getelementptr inbounds double, double* %44, i64 %46
store double %43, double* %47
%48 = load i32, i32* %10
%49 = icmp eq i32 %48, 2
br i1 %49, label %50, label %61
50: ; preds = %39
%51 = load [2 x double]*, [2 x double]** %9
%52 = load i32, i32* %10
%53 = sext i32 %52 to i64
%54 = getelementptr inbounds [2 x double], [2 x double]* %51, i64 %53
%55 = getelementptr inbounds [2 x double], [2 x double]* %54, i64 0, i64 1
store double -1.000000e+00, double* %55
%56 = load [2 x double]*, [2 x double]** %9
%57 = load i32, i32* %10
%58 = sext i32 %57 to i64
%59 = getelementptr inbounds [2 x double], [2 x double]* %56, i64 %58
%60 = getelementptr inbounds [2 x double], [2 x double]* %59, i64 0, i64 0
store double -1.000000e+00, double* %60
br label %90
61: ; preds = %39
store i32 0, i32* %11
br label %62
62: ; preds = %86, %61
%63 = load i32, i32* %11
%64 = icmp slt i32 %63, 2
br i1 %64, label %65, label %89
65: ; preds = %62
%66 = load i32, i32* %10
%67 = load i32, i32* %11
%68 = icmp eq i32 %66, %67
br i1 %68, label %69, label %77
69: ; preds = %65
%70 = load [2 x double]*, [2 x double]** %9
%71 = load i32, i32* %10
%72 = sext i32 %71 to i64
%73 = getelementptr inbounds [2 x double], [2 x double]* %70, i64 %72
%74 = load i32, i32* %11
%75 = sext i32 %74 to i64
%76 = getelementptr inbounds [2 x double], [2 x double]* %73, i64 0, i64 %75
store double 1.000000e+00, double* %76
br label %85
77: ; preds = %65
%78 = load [2 x double]*, [2 x double]** %9
%79 = load i32, i32* %10
%80 = sext i32 %79 to i64
%81 = getelementptr inbounds [2 x double], [2 x double]* %78, i64 %80
%82 = load i32, i32* %11
%83 = sext i32 %82 to i64
%84 = getelementptr inbounds [2 x double], [2 x double]* %81, i64 0, i64 %83
store double 0.000000e+00, double* %84
br label %85
85: ; preds = %77, %69
br label %86
86: ; preds = %85
%87 = load i32, i32* %11
%88 = add nsw i32 %87, 1
store i32 %88, i32* %11
br label %62
89: ; preds = %62
br label %90
90: ; preds = %89, %50
br label %91
91: ; preds = %90
%92 = load i32, i32* %10
%93 = add nsw i32 %92, 1
store i32 %93, i32* %10
br label %36
94: ; preds = %36
store i32 3, i32* %12
%95 = load i32, i32* %6
%96 = icmp sgt i32 %95, 1
br i1 %96, label %97, label %164
97: ; preds = %94
%98 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 0
%99 = load double, double* %98
%100 = fmul double -2.000000e+00, %99
%101 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 1
%102 = load double, double* %101
%103 = fmul double %100, %102
%104 = load double*, double** %8
%105 = getelementptr inbounds double, double* %104, i64 3
store double %103, double* %105
%106 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 1
%107 = load double, double* %106
%108 = fmul double -2.000000e+00, %107
%109 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 2
%110 = load double, double* %109
%111 = fmul double %108, %110
%112 = load double*, double** %8
%113 = getelementptr inbounds double, double* %112, i64 4
store double %111, double* %113
%114 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 0
%115 = load double, double* %114
%116 = fmul double -2.000000e+00, %115
%117 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 2
%118 = load double, double* %117
%119 = fmul double %116, %118
%120 = load double*, double** %8
%121 = getelementptr inbounds double, double* %120, i64 5
store double %119, double* %121
%122 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 1
%123 = load double, double* %122
%124 = fmul double -2.000000e+00, %123
%125 = load [2 x double]*, [2 x double]** %9
%126 = getelementptr inbounds [2 x double], [2 x double]* %125, i64 3
%127 = getelementptr inbounds [2 x double], [2 x double]* %126, i64 0, i64 0
store double %124, double* %127
%128 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 0
%129 = load double, double* %128
%130 = fmul double -2.000000e+00, %129
%131 = load [2 x double]*, [2 x double]** %9
%132 = getelementptr inbounds [2 x double], [2 x double]* %131, i64 3
%133 = getelementptr inbounds [2 x double], [2 x double]* %132, i64 0, i64 1
store double %130, double* %133
%134 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 1
%135 = load double, double* %134
%136 = fmul double 2.000000e+00, %135
%137 = load [2 x double]*, [2 x double]** %9
%138 = getelementptr inbounds [2 x double], [2 x double]* %137, i64 4
%139 = getelementptr inbounds [2 x double], [2 x double]* %138, i64 0, i64 0
store double %136, double* %139
%140 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 0
%141 = load double, double* %140
%142 = call double @llvm.fmuladd.f64(double 2.000000e+00, double %141, double -2.000000e+00)
%143 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 1
%144 = load double, double* %143
%145 = call double @llvm.fmuladd.f64(double 4.000000e+00, double %144, double %142)
%146 = load [2 x double]*, [2 x double]** %9
%147 = getelementptr inbounds [2 x double], [2 x double]* %146, i64 4
%148 = getelementptr inbounds [2 x double], [2 x double]* %147, i64 0, i64 1
store double %145, double* %148
%149 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 0
%150 = load double, double* %149
%151 = call double @llvm.fmuladd.f64(double 4.000000e+00, double %150, double -2.000000e+00)
%152 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 1
%153 = load double, double* %152
%154 = call double @llvm.fmuladd.f64(double 2.000000e+00, double %153, double %151)
%155 = load [2 x double]*, [2 x double]** %9
%156 = getelementptr inbounds [2 x double], [2 x double]* %155, i64 5
%157 = getelementptr inbounds [2 x double], [2 x double]* %156, i64 0, i64 0
store double %154, double* %157
%158 = getelementptr inbounds [3 x double], [3 x double]* %13, i64 0, i64 0
%159 = load double, double* %158
%160 = fmul double 2.000000e+00, %159
%161 = load [2 x double]*, [2 x double]** %9
%162 = getelementptr inbounds [2 x double], [2 x double]* %161, i64 5
%163 = getelementptr inbounds [2 x double], [2 x double]* %162, i64 0, i64 1
store double %160, double* %163
store i32 6, i32* %12
br label %164
164: ; preds = %97, %94
%165 = load i32, i32* %12
store i32 %165, i32* %5
br label %166
166: ; preds = %164, %16
%167 = load i32, i32* %5
ret i32 %167
}

LLVM IR (-O2):
define i32 @TriShapeAndDrv(i32 %0, double* nocapture %1, double* nocapture writeonly %2, [2 x double]* nocapture writeonly %3) {
%5 = icmp sgt i32 %0, 2
br i1 %5, label %44, label %6
6: ; preds = %4
%7 = bitcast double* %1 to <2 x double>*
%8 = load <2 x double>, <2 x double>* %7
%9 = extractelement <2 x double> %8, i64 0
%10 = fsub double 1.000000e+00, %9
%11 = extractelement <2 x double> %8, i64 1
%12 = fsub double %10, %11
store double %9, double* %2
%13 = bitcast [2 x double]* %3 to <2 x double>*
store <2 x double> <double 1.000000e+00, double 0.000000e+00>, <2 x double>* %13
%14 = getelementptr inbounds double, double* %2, i64 1
store double %11, double* %14
%15 = getelementptr inbounds [2 x double], [2 x double]* %3, i64 1, i64 0
%16 = bitcast double* %15 to <2 x double>*
store <2 x double> <double 0.000000e+00, double 1.000000e+00>, <2 x double>* %16
%17 = getelementptr inbounds double, double* %2, i64 2
store double %12, double* %17
%18 = getelementptr inbounds [2 x double], [2 x double]* %3, i64 2, i64 0
%19 = bitcast double* %18 to <2 x double>*
store <2 x double> <double -1.000000e+00, double -1.000000e+00>, <2 x double>* %19
%20 = icmp eq i32 %0, 2
br i1 %20, label %21, label %44
21: ; preds = %6
%22 = getelementptr inbounds double, double* %2, i64 3
%23 = fmul <2 x double> %8, <double -2.000000e+00, double -2.000000e+00>
%24 = shufflevector <2 x double> %8, <2 x double> undef, <2 x i32> <i32 1, i32 undef>
%25 = insertelement <2 x double> %24, double %12, i64 1
%26 = fmul <2 x double> %23, %25
%27 = bitcast double* %22 to <2 x double>*
store <2 x double> %26, <2 x double>* %27
%28 = extractelement <2 x double> %23, i64 0
%29 = fmul double %28, %12
%30 = getelementptr inbounds double, double* %2, i64 5
store double %29, double* %30
%31 = getelementptr inbounds [2 x double], [2 x double]* %3, i64 3, i64 0
%32 = shufflevector <2 x double> %23, <2 x double> poison, <2 x i32> <i32 1, i32 0>
%33 = bitcast double* %31 to <2 x double>*
store <2 x double> %32, <2 x double>* %33
%34 = fmul double %11, 2.000000e+00
%35 = getelementptr inbounds [2 x double], [2 x double]* %3, i64 4, i64 0
store double %34, double* %35
%36 = getelementptr inbounds [2 x double], [2 x double]* %3, i64 4, i64 1
%37 = shufflevector <2 x double> %8, <2 x double> undef, <2 x i32> zeroinitializer
%38 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %37, <2 x double> <double 2.000000e+00, double 4.000000e+00>, <2 x double> <double -2.000000e+00, double -2.000000e+00>)
%39 = shufflevector <2 x double> %8, <2 x double> poison, <2 x i32> <i32 1, i32 1>
%40 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %39, <2 x double> <double 4.000000e+00, double 2.000000e+00>, <2 x double> %38)
%41 = bitcast double* %36 to <2 x double>*
store <2 x double> %40, <2 x double>* %41
%42 = fmul double %9, 2.000000e+00
%43 = getelementptr inbounds [2 x double], [2 x double]* %3, i64 5, i64 1
store double %42, double* %43
br label %44
44: ; preds = %6, %21, %4
%45 = phi i32 [ 0, %4 ], [ 6, %21 ], [ 3, %6 ]
ret i32 %45
}