Skip to main content
Giac provides native Node.js bindings that allow you to leverage powerful computer algebra capabilities in your JavaScript applications. The bindings are built using Node.js Native Addons (N-API).

Installation

The Node.js package is no longer actively updated but remains functional for existing projects.
Install the giac package from npm:
npm install giac

Prerequisites

To build the native bindings from source, you need:
  • Node.js 10.0 or higher
  • C++ compiler with C++11 support
  • Python 2.7 or 3.x (for node-gyp)
  • GMP and MPFR libraries
sudo apt-get install build-essential libgmp-dev libmpfr-dev

Quick Start

Basic Usage

Here’s a simple example of evaluating mathematical expressions:
const giac = require('giac');

// Evaluate expressions
console.log(giac.evaluate("expand((x+y)^3)"));
// Output: x^3+y^3+3*x*y^2+3*x^2*y

console.log(giac.evaluate("expand((x+y)^4)"));
// Output: x^4+y^4+4*x*y^3+6*x^2*y^2+4*x^3*y

console.log(giac.evaluate("2^50"));
// Output: 1125899906842624

Interactive REPL

The package includes a command-line interface:
node nodegiac.js
This launches an interactive session:
This is a minimalist command line version of NodeGiac
Enter expressions to evaluate
Example: factor(x^4-1); simplify(sin(3x)/sin(x))
int(1/(x^4-1)); int(1/(x^4+1)^4,x,0,inf)
f(x):=sin(x^2); f'(2); f'(y)
Press CTRL-D to stop

1>> factor(x^4-1)
1<< (x-1)*(x+1)*(x^2+1)

API Reference

evaluate(expression)

Evaluates a Giac expression and returns the result as a string. Parameters:
  • expression (string): The mathematical expression to evaluate
Returns:
  • (string): The result of the evaluation
Examples:
const giac = require('giac');

// Factor polynomials
console.log(giac.evaluate("factor(x^4-1)"));
// Output: (x-1)*(x+1)*(x^2+1)

// Simplify expressions
console.log(giac.evaluate("simplify(sin(3x)/sin(x))"));
// Output: 3-4*sin(x)^2

// GCD computation
console.log(giac.evaluate("gcd(x^4-1,x^3-1)"));
// Output: x-1

Building Native Bindings

The native bindings are built using binding.gyp configuration:

Configuration

{
  "targets": [
    {
      "target_name": "giac",
      "sources": [
        "<!@(node -p \"require('fs').readdirSync('./src/giac/cpp/').map(f=>'src/giac/cpp/'+f).join(' ')\")",
        "src/nodegiac/cpp/nodegiac.cc"
      ],
      "include_dirs": ["src/giac/headers"],
      "defines": [
        "GIAC_GGB",
        "VERSION=\"1.2.3\"",
        "IN_GIAC",
        "HAVE_SYSCONF",
        "HAVE_NO_HOME_DIRECTORY",
        "TIMEOUT",
        "HAVE_MPFR_1",
        "HAVE_LIBMPFR"
      ]
    }
  ]
}

Platform-Specific Settings

"cflags_cc": ["-fexceptions", "-fpermissive"],
"cflags_cc!": ["-fno-rtti"],
"link_settings": {
  "libraries": ["-lgmp", "-lmpfr"]
},
"defines+": ["HAVE_LIBPTHREAD"]

Build from Source

# Clone repository
git clone <repository-url>
cd giac

# Install dependencies
npm install

# Build native addon
npm run build

Implementation Details

The Node.js binding is implemented using V8 and N-API:
#include <node.h>
#include <v8.h>
#include "giac.h"

using namespace v8;
using namespace giac;

context ct;

void Evaluate(const v8::FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = Isolate::GetCurrent();
  Local<Context> context = isolate->GetCurrentContext();
  HandleScope scope(isolate);
  std::string line_out;

  // Convert JS string to C++ string
  v8::String::Utf8Value param1(isolate, 
    args[0]->ToString(context).ToLocalChecked());
  std::string line_in = std::string(*param1);

  // Evaluate using Giac
  gen g = gen(line_in, &ct);
  try {
    line_out = giac::print(giac::eval(g, &ct), &ct);
  } catch (runtime_error & err) {
    line_out = std::string("ERROR: ") + err.what();
  }

  // Return result to JavaScript
  Local<Value> line_out_v8 = String::NewFromUtf8(
    isolate, line_out.c_str(), 
    NewStringType::kNormal).ToLocalChecked();
  args.GetReturnValue().Set(line_out_v8);
}

NODE_MODULE(giac, Initialize)

Creating a REPL

Here’s how to create an interactive REPL using Node.js readline:
const giac = require('giac');
const readline = require('readline');

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
  terminal: false
});

console.log("Giac REPL - Enter expressions to evaluate");
console.log("Press CTRL-D to exit\n");

let lineNumber = 1;

rl.on('line', function(line) {
  // Echo input
  console.log(`${lineNumber}>> ${line}`);
  
  // Evaluate expression
  const result = giac.evaluate(line);
  console.log(`${lineNumber}<< ${result}`);
  
  lineNumber++;
});

rl.on('close', function() {
  console.log("\nGoodbye!");
  process.exit(0);
});

GeoGebra Mode

Enable GeoGebra-specific features:
const giac = require('giac');

// Enable GeoGebra mode
console.log(giac.evaluate('caseval("init geogebra")'));
// Output: "geogebra mode on"

// Lists become sets in GeoGebra mode
console.log(giac.evaluate('[1]'));
// Output: {1}

// High precision evaluation
console.log(giac.evaluate('evalf(7,15)'));
// Output: 7.00000000000000

// Disable GeoGebra mode
console.log(giac.evaluate('caseval("close geogebra")'));
// Output: "geogebra mode off"

Advanced Usage

Processing Multiple Expressions

const giac = require('giac');

const expressions = [
  'factor(x^4-1)',
  'solve(x^2-3*x+2=0)',
  'int(sin(x))',
  'limit(sin(x)/x,x=0)'
];

expressions.forEach((expr, index) => {
  console.log(`${index + 1}. ${expr}`);
  console.log(`   => ${giac.evaluate(expr)}\n`);
});

Error Handling

const giac = require('giac');

function safeEvaluate(expression) {
  try {
    const result = giac.evaluate(expression);
    
    // Check for error prefix
    if (result.startsWith('ERROR:')) {
      throw new Error(result);
    }
    
    return result;
  } catch (error) {
    console.error(`Failed to evaluate "${expression}":`, error.message);
    return null;
  }
}

console.log(safeEvaluate('factor(x^2-1)'));  // Success
console.log(safeEvaluate('invalid syntax'));  // Error

Integration with Express

const express = require('express');
const giac = require('giac');

const app = express();
app.use(express.json());

app.post('/evaluate', (req, res) => {
  const { expression } = req.body;
  
  if (!expression) {
    return res.status(400).json({ error: 'Expression required' });
  }
  
  try {
    const result = giac.evaluate(expression);
    res.json({ expression, result });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.listen(3000, () => {
  console.log('Giac API listening on port 3000');
});

Performance Tips

  • Batch expressions: Process multiple expressions in sequence to reuse the Giac context
  • Cache results: Store frequently-used computation results
  • Timeouts: Long computations may block the Node.js event loop
  • Worker threads: Consider using worker threads for CPU-intensive operations
Giac computations run on the main thread and may block the event loop for complex expressions. Consider implementing timeouts or using worker threads for production applications.

Troubleshooting

Install GMP development headers:Linux: sudo apt-get install libgmp-devmacOS: brew install gmpWindows: Ensure MPIR libraries are in your PATH
Try rebuilding the native addon:
npm rebuild giac
This usually indicates a memory issue. Make sure:
  • You’re using compatible Node.js and V8 versions
  • GMP/MPFR libraries are correctly installed
  • The expression syntax is valid

Next Steps

C++ Integration

Learn about the underlying C++ library

API Reference

Explore available Giac functions

WebAssembly

Use Giac in web browsers

Algebra API

Explore polynomial and algebra functions

Build docs developers (and LLMs) love